Redis 规范
Key 规范
- 命名
- 使用服务名、模块名作为 Key 的固定前缀防止冲突,层级之间使用冒号分隔,例如:
order:invoice:{id}
订单服务发票模块信息缓存
- 尽量简洁,在保证语义的前提下简化 Key 的长度,例如:
user:{uid}:friends:messages:{mid}
简化为 u:{uid}:fr:m:{mid}
- 不要包含特殊字符,例如空格、换行、单双引号以及其他转义字符
- 有效期
- 正常情况下所有的 Key 必须设置过期时间
- 设置合理的有效期,避免集中到期导致雪崩
- 不应该有超长有效期的Key,有效期超过一个月需要确认
- 可针对热点 key 设置永不过期(需要审批)
- 长度
性能规范
- 数据结构值约束
- 简单的 string 类型 Key,单 Key 对应 Value 大小不超过 10K, 建议 1K 之内,太大会影响性能、网卡流量、慢查询,导致分片不均,QPS 下降
- 测试数据: 单 Key 对应 Value 不同时做 Set 操作,QPS 测试结果:
- Size:100byte 1k 10k 50k 100k 500k
- QPS:9.7w 7.8w 7.3w 6.8w 4.2w 6400
- 复杂类型 hash、list、set、zset 单 Key 对应 Value 大小不超过 1M,Key 的元素个数不要超过 1000
- 复杂类型的 bigkey 不要使用 del 删除,使用 hscan、sscan、zscan 方式渐进式删除,同时要注意防止 bigkey 过期时间自动删除问题,例如一个 200 万的 zset 设置 1 小时过期,会触发 del 操作,造成阻塞,而且该操作不会不出现在慢查询中(latency可查)
- 多 Key 命令约束
- 单个多 Key 命令(mset、mget、del)的并发度限制在 100 以内
- 测试数据:预置单 KV 大小 100 字节的 string,测试 mget 命令在不同并发度的平响时间时 QPS 测试结果:
并发数 | 10 | 50 | 100 | 300 | 500 | 750 |
---|
平响时间(ms) | 2.7 | 3.5 | 4.2 | 8 | 10 | 39 |
QPS | 7500 | 5300 | 4200 | 2100 | 1400 | 950 |
- 使用批量操作提高效率
- 原生命令:例如 mget、mset
- 非原生命令:可以使用 pipeline 提高效率
- 原生是原子操作,pipeline 是非原子操作,pipeline 可以打包不同的命令,需要客户端和服务端同时支持
- 流水线命令约束
- 每个 pipeline 批次下 key 数量限制在 500 以内,最好控制在 100 以内
- 流水线命令不保证事务,只是将多次执行的命令进行合并,减少客户端与集群网络建立连接的开销
- 禁止同时操作多个 Set 的命令
- 禁止同时操作多个 List 的命令
- 尽量让 Value 是数字,而不是字符串
- 因为数字存储空间远比字符串要小,当数字或字符串Value均可以满足业务需求时,优先使用 Value 是数字的方案
- 使用 Hash 来替代内容是 JSON 的 String
- 对于 JSON 格式存储 Key-Value 内容的 String,可以使用 Hash 来替换,将 Key 存储在 Field 中,这样的好处是增删改单个 Key-Value 不再需要更新整个 JSON,性能更好
hmset user:1 name tom age 19 favor football
- 设置好最大内存淘汰策略,参考 Key 的生与死
- 监控
命令使用规范
- O(N) 命令关注 N 的数量
- hgetall、lrange、smembers、zrange、sinter 等并非不能使用,但是需要明确 N 的值。有遍历的需求可以使用 hscan、sscan、zscan 代替
- 禁用命令
- 禁止线上使用 keys、flushall、flushdb 等,通过 redis 的 rename 机制禁掉命令,或者使用 scan 的方式渐进式处理
- 合理使用 select
- redis 的多数据库较弱,使用数字进行区分,很多客户端支持较差,同时多业务用多数据库实际还是单线程处理,会有干扰
- Redis 事务功能较弱,不建议过多使用
- Redis 的事务功能较弱(不支持回滚),而且集群版本(自研和官方)要求一次事务操作的 Key 必须在一个 slot 上(可以使用hashtag功能解决)
- Redis 集群版本在使用 Lua 上有特殊要求
- 所有 Key 都应该由 KEYS 数组来传递,redis.call/pcall 里面调用的 redis 命令,key的位置,必须是 KEYS array, 否则直接返回 error,"-ERR bad lua script for redis cluster, all the keys that the script uses should be passed using the KEYS array"
- 所有 Key,必须在 1 个 slot 上,否则直接返回 error, "-ERR eval/evalsha command keys must in same slot"
- 必要情况下使用 monitor 命令时,要注意不要长时间使用
参考资料