键值对使用规范
规范一:key 的命名规范
把业务名作为前缀,然后用冒号分隔,再加上具体的业务数据名。这样一来,我们可以通过 key 的前缀区分不同的业务数据,就不用在多个数据库间来回切换了。
- 一个 Redis 实例默认可以支持 16 个数据库,我们可以把不同的业务数据分散保存到不同的数据库中。
- 但是,在使用不同数据库时,客户端需要使用 SELECT 命令进行数据库切换,相当于增加了一个额外的操作。
我们在设置 key 的名称时,要注意控制 key 的长度
- 当 key 字符串的长度增加时,SDS 中的元数据也会占用更多内存空间
- 为了减少 key 占用的内存空间,建议:对于业务名或业务数据名,可以使用相应的英文单词的首字母表示,(比如 user 用 u 表示,message 用 m),或者是用缩写表示(例如 unique visitor 使用 uv)
规范二:避免使用 bigkey
- 情况一:键值对的值大小本身就很大,例如 value 为 1MB 的 String 类型数据。为了避免 String 类型的 bigkey,在业务层,我们要尽量把 String 类型的数据大小控制在 10KB 以下。
- 情况二:键值对的值是集合类型,集合元素个数非常多,例如包含 100 万个元素的 Hash 集合类型数据。为了避免集合类型的 bigkey,建议尽量把集合类型的元素个数控制在 1 万以下。
规范三:使用高效序列化方法和压缩方法
规范四:使用整数对象共享池
数据保存规范
规范一:使用 Redis 保存热数据
规范二:不同的业务数据分实例存储
规范三:在数据保存时,要设置过期时间
规范四:控制 Redis 实例的容量
Redis 单实例的内存大小都不要太大,建议设置在 2~6GB 。这样一来,无论是 RDB 快照,还是主从集群进行数据同步,都能很快完成,不会阻塞正常请求的处理。
命令使用规范
规范一:线上禁用部分命令
- KEYS,按照键值对的 key 内容进行匹配,返回符合匹配条件的键值对,该命令需要对 Redis 的全局哈希表进行全表扫描,严重阻塞 Redis 主线程;
- FLUSHALL,删除 Redis 实例上的所有数据,如果数据量很大,会严重阻塞 Redis 主线程;
- FLUSHDB,删除当前数据库中的数据,如果数据量很大,同样会阻塞 Redis 主线程。
具体的做法是,管理员用 rename-command 命令在配置文件中对这些命令进行重命名,让客户端无法使用这些命令
规范二:慎用 MONITOR 命令
规范三:慎用全量操作命令
对于集合类型的数据来说,如果想要获得集合中的所有元素,一般不建议使用全量操作的命令(例如 Hash 类型的 HGETALL、Set 类型的 SMEMBERS)。这些操作会对 Hash 和 Set 类型的底层数据结构进行全量扫描,如果集合类型数据较多的话,就会阻塞 Redis 主线程。
建议
- 使用 SSCAN、HSCAN 命令分批返回集合中的数据,减少对主线程的阻塞
- 化整为零,把一个大的 Hash 集合拆分成多个小的 Hash 集合。这个操作对应到业务层,就是对业务数据进行拆分,按照时间、地域、用户 ID 等属性把一个大集合的业务数据拆分成多个小集合数据。例如,当你统计用户的访问情况时,就可以按照天的粒度,把每天的数据作为一个 Hash 集合
- 如果集合类型保存的是业务数据的多个属性,而每次查询时,也需要返回这些属性,那么,你可以使用 String 类型,将这些属性序列化后保存,每次直接返回 String 数据就行,不用再对集合类型做全量扫描了
小结
规范类别 | 规范内容 |
---|---|
强制 | 禁用 KEYS、FLUSHALL、FLUSHDB 命令 |
推荐 | 使用业务名做 key 的前缀,并使用缩写形式 |
控制 key 的长度 | |
使用高效序列化方法和压缩方法 | |
使用整数对象共享池 | |
不同业务数据保存到不同实例 | |
数据保存时设置过期时间 | |
慎用 MONITOR 命令 | |
慎用全量操作命令 | |
建议 | 控制 String 类型数据的大小不超过 10KB |
控制集合类型的元素个数不超过 1 万个 | |
使用 Redis 保存热数据 | |
把 Redis 实例的容量控制在 2~6 GB |
精选留言
Kaito
业务层面主要面向的业务开发人员:
- key 的长度尽量短,节省内存空间
- 避免 bigkey,防止阻塞主线程
- 4.0+版本建议开启 lazy-free
- 把 Redis 当作缓存使用,设置过期时间
- 不使用复杂度过高的命令,例如SORT、SINTER、SINTERSTORE、ZUNIONSTORE、ZINTERSTORE
- 查询数据尽量不一次性查询全量,写入大量数据建议分多批写入
- 批量操作建议 MGET/MSET 替代 GET/SET,HMGET/HMSET 替代 HGET/HSET
- 禁止使用 KEYS/FLUSHALL/FLUSHDB 命令
- 避免集中过期 key
- 根据业务场景选择合适的淘汰策略
- 使用连接池操作 Redis,并设置合理的参数,避免短连接
- 只使用 db0,减少 SELECT 命令的消耗
- 读请求量很大时,建议读写分离,写请求量很大,建议使用切片集群
运维层面主要面向的是 DBA 运维人员:
- 按业务线部署实例,避免多个业务线混合部署,出问题影响其他业务
- 保证机器有足够的 CPU、内存、带宽、磁盘资源
- 建议部署主从集群,并分布在不同机器上,slave 设置为 readonly
- 主从节点所部署的机器各自独立,尽量避免交叉部署,对从节点做维护时,不会影响到主节点
- 推荐部署哨兵集群实现故障自动切换,哨兵节点分布在不同机器上
- 提前做好容量规划,防止主从全量同步时,实例使用内存突增导致内存不足
- 做好机器 CPU、内存、带宽、磁盘监控,资源不足时及时报警,任意资源不足都会影响 Redis 性能
- 实例设置最大连接数,防止过多客户端连接导致实例负载过高,影响性能
- 单个实例内存建议控制在 10G 以下,大实例在主从全量同步、备份时有阻塞风险
- 设置合理的 slowlog 阈值,并对其进行监控,slowlog 过多需及时报警
- 设置合理的 repl-backlog,降低主从全量同步的概率
- 设置合理的 slave client-output-buffer-limit,避免主从复制中断情况发生
- 推荐在从节点上备份,不影响主节点性能
- 不开启 AOF 或开启 AOF 配置为每秒刷盘,避免磁盘 IO 拖慢 Redis 性能
- 调整 maxmemory 时,注意主从节点的调整顺序,顺序错误会导致主从数据不一致
- 对实例部署监控,采集 INFO 信息时采用长连接,避免频繁的短连接
- 做好实例运行时监控,重点关注 expired_keys、evicted_keys、latest_fork_usec,这些指标短时突增可能会有阻塞风险
- 扫描线上实例时,记得设置休眠时间,避免过高 OPS 产生性能抖动