业务使用规范
规范 | 规范说明 | 级别 | 备注 |
---|---|---|---|
业务数据分离 | 防止由于Redis故障或不可用影响所有相关业务收到干扰 | 建议 | 业务数据分离,避免多个应用使用一个Redis实例,不相干的业务拆分,公共数据做服务化 |
完善redis的容错处理 | 缓存可能会遇到基础设施的故障或主备切换,应用需要对可能的故障和慢请求做容错处理。 | 建议 | 缓存访问失败时,具备降级措施,从DB获取数据;或者具备容灾措施,自动切换到另一个Redis使用; |
避免redis内存使用量超过80% | 避云主机会有一定的内存冗余,但是redis内存过高时,redis全量持久化时引入的COPY-ON-WRITE机制带来额外的内存消耗,再加上大内存带来的内存碎片和云主机相关的管理进程消耗,容易触发操作系统OOM KILL | 强制 | 建议及时做扩容处理 |
防止缓存击穿 | 防止缓存击穿,推荐搭配本地缓存使用Redis,对于热点数据建立本地缓存。本地缓存数据使用异步方式进行刷新 | 建议 | - |
就近部署业务 | 避免网络延迟将极大影响读写性能,如果对于时延较为敏感,请避免使用跨AZ Redis实例 | 建议 | - |
不当成消息队列 | 发布订阅场景下,不建议作为消息队列使用。redis的PUB/SUB支持的性能有限。 | 强制 | 如果需要消息队列,建议改用kafka或rabbitmq |
Key名称的使用规范
规范 | 规范说明 | 级别 | 备注 |
---|---|---|---|
使用统一的命名规范 | 一般使用业务名(或数据库名)为前缀,用冒号分隔 | 建议 | 例如,业务名:表名:id |
控制key名称的长度 | 在保证语义清晰的情况下,Key的长度越短越好。有些常用单词可使用缩写 | 建议 | 例如,user缩写为u,messages缩写为msg。建议长度不超过128字节。 |
名称中不要包含特殊字符 | 禁止包含特殊字符,如空格、换行、单双引号、中文或其他转义字符 | 强制 | 大括号({})为Redis的hash tag语义,如果使用cluster集群实例, KEY名称需要正确使用,避免引发数据倾斜,数据都分在同一个SLOT上。 |
Value值的使用规范
规范 规范说明 级别 备注 要避免大Key、热Key 大Key会带来网卡流量风暴和慢查询,要避免出现大Key和热KEY 强制 一般string类型控制在10KB以内,hash、list、set、zset元素个数不要超过1000 选择合适的数据类 选择合适的数据类型能够节省内存、带宽和提升性能。 建议 比如存储用户的信息,可用使用多个key,使用set u:1:name "X"、set u:1:age 20这样存储,也可以使用hash数据结构,存储成1个key,设置用户属性时使用hmset一次设置多个,同时这样存储也能节省内存 设置合理的过期时间 最好是过期时间打散,不要集中在某个时间点过期。 建议 避免Redis因为处理大量过期KEY导致CPU使用率飙高导致性能不稳定。
Redis命令的常用规范
规范 规范说明 级别 备注 小心使用时间复杂度为O(N)的命令 对于时间复杂度为O(N)的命令如果N值较大,可能会导致Redis执行过慢,影响整体性能和稳定性 强制 例如:hgetall、lrange、smembers、zrange、sinter这些命令都是做全集操作,如果元素很多,是很耗性能的可使用hscan、sscan、zscan这些分批扫描的命令替代 命令禁用 部分命令是禁止使用的,需要最好提早了解清楚 强制 使用前,请参考Redis命令兼容性和WebCli命令兼容性 慎重使用select Redis多数据库支持较弱,多业务用多数据库实际还是单线程处理,会有干扰 建议 需要多DB的场合,建议拆分多个redis使用 CLUSTER集群实例不支持多DB 批量操作 如果有批量操作,可使用mget、mset或pipeline,提高效率,但要注意控制一次批量操作的元素个数免得导致执行过慢,占用Redis过多的资源 建议 如果有批量操作,可使用mget、mset或pipeline,提高效率,但要注意控制一次批量操作的元素个数mget、mset和pipeline的区别如下:
mget和mset是原子操作,pipeline是非原子操作
pipeline可以打包不同的命令,mget和mset做不到
使用pipeline,需要客户端和服务端同时支持
lua脚本执行耗时 lua脚本的执行超时时间为5秒钟,建议不要在lua脚本中使用比较耗时的代码 强制 比如长时间的sleep、大的循环等语句 避免在lua脚本中使用随机函数 调用lua脚本时,建议不要使用随机函数去指定key,否则在主备节点上执行结果不一致,从而导致主备节点数据不一致 强制 - 遵循CLUSTER集群实例使用lua的限制 遵循CLUSTER集群实例使用lua的限制 强制 cluster集群实例使用lua有如下限制:
使用EVAL和EVALSHA命令时,命令参数中必须带有至少1个key,否则客户端会提示“ERR eval/evalsha numkeys must be bigger than zero in redis cluster mode”的错误
使用EVAL和EVALSHA命令时,cluster集群实例使用第一个key来计算slot,用户代码需要保证操作的key是在同一个slot
不要直接使用del命令删除大Key 删除大Key时,不要直接使用del命令因为del命令是阻塞的,也会同时阻塞其他客户端请求无法正常执行 强制 Redis 4.0后的版本可以通过UNLINK命令安全地删除大Key,该命令是异步非阻塞
对于 4.0之前的版本:
如果是Hash类型的大Key,推荐使用hscan + hdel
如果是List类型的大Key,推荐使用ltrim
如果是Set类型的大Key,推荐使用sscan + srem
如果是SortedSet类型的大Key,推荐使用zscan + zrem
的
控制pipeline命令个数 使用Pipeline时,建议不要一次太多命令因为会占用大量Redis资源和执行时间较长,可能会卡住其他请求无法执行 建议 单次建议不超过100,同时也需要考虑实际元素字节数大小情况 合理使用发布订阅命令 不建议将 Redis 当作消息队列使用Redis 当作消息队列使用,会有容量、网络、效率、功能方面的多种问题 建议 如需要消息队列,可使用高吞吐的Kafka或者高可靠的RabbitMQ Redis事务限制 Redis事务是不支持回滚的如果事务在中途某个命令失败了,那么前面的命令依然会执行成功 建议 -
SDK使用规范
规范 规范说明 等级 备注 使用连接池+长连接 短连接性能差,建议使用连接池+长连接,可以有效控制连接,同时提高效率 建议 推荐使用JedisPool或者JedisCluster连接实例。 避免使用Lettuce客户端 Jedis客户端在面对连接异常,网络抖动等场景下的异常处理和检测能力明显强于Lettuce,可靠性更强 建议 建议使用Jedis 客户端需要对可能的故障和慢请求做容错处理 由于Redis服务可能因网络波动或基础设置故障的影响,引发主备切换、命令超时或慢请求等现象,需要在客户端内设计合理的容错重试机制 强制 - 合理设置重试时间和次数 根据业务要求合理设置容错处理的重试时间和次数,避免不合适的设置导致对服务的可用性收到影响 强制
如果超时重试时间设置的非常短,可能引发重试风暴,极易引发业务层雪崩
如果重试时间设置得较长或者重试次数设置得较大,则可能导致在主备倒换情况下业务恢复较慢
运维管理规范
规范 规范说明 等级 备注 开启密码登录 生产环境需要开启Redis密码登录验证 强制 - 验证业务的故障处理能力或容灾逻辑 在测试环境或者预生产环境中组织演练,验证在Redis主备切换、宕机或者扩缩容场景下业务的可靠性 建议 - 监控实践 关注Redis负载,在过载前提前扩容 强制 根据告警基线配置告警:配置节点cpu、内存、带宽等告警 检查各个节点的内存使用率 例行检查各个节点的内存使用率,查看主节点内存使用率是否有不均衡的状态 建议 内存使用率不均衡说明存在大Key问题,需要进行大Key拆分及优化 开启热Key分析 开启热Key例行分析,并分析是否有Key频繁调用 建议 - Redis慢日志 例行巡检Redis慢日志命令 建议 分析慢日志,并尽快从业务上进行修复