【Redis运维】Redis开发与运维规范

TangLu Redis 2021-11-29 1246 0

一、规范目的

Redis在业务系统中作为缓存角色起着重要作用,如果结构规划不合理、命令使用不规范,除了增大运维难度,还会对业务系统带来性能和可用性问题。为避免出现此类问题,特制定本使用规范,开发、运维、测试及其他相关团队在使用Redis过程中均需要按照规范化、流程化的使用规则进行操作。本规范按照使用方作为维度分为开发侧与运维侧,并且以【强制】、【建议】、【参考】3个级别进行标注。其中【强制】级别需严格遵守,否则危害极大;【建议】级别建议遵守,可提升性能、便于运维;【参考】级别根据业务特点参考实施。


Redis使用规范(开发侧)

1、强制】禁止在线上环境使用高危命令。高危命令包括keys、flushdb、flushall。由于Redis对读写请求都为单线程工作,如果执行命令涉及大量操作或耗时较长,都会阻塞主线程导致其它请求无法正常进行。

2、强制】数据要有重加载机制。Redis作为内存数据库,要考虑数据丢失风险,程序在发生Redis数据丢失时要可进行重加载。

3、强制聚合命令需谨慎使用对于数据的聚合操作应由客户端完成,尽量避免让Redis进行SUNIONSTORE、SDIFFSTORE、SINTERSTORE等聚合命令,这些操作会消耗大量CPU资源,导致主线程繁忙。如果不可避免要执行这类命令,要保证N尽量小(N<300),有遍历需求可使用 hscan、sscan、zscan作为替代。

4、强制全量查询命令需谨慎使用。随着业务发展,集合类型数据元素会越来越多,使用HGETALL、SINTER、LRANGE、ZRANGE等时间复杂度O(N)的命令都会对底层数据结构进行全量扫描 ,导致阻塞 Redis 主线程。如果业务场景需要获取全量数据建议使用HSCAN、SSCAN等命令分批返回集合数据,或者将大集合按照不同维度拆成多个集合。

5、强制阻塞式命令需谨慎使用。Redis为部分命令提供了命令的阻塞版本,如BLPOP、BLMOVE、BLPOPPUSH、BLMPOP,这些命令在列表没有元素的场景下会持续阻塞客户端。

6、【建议】合理配置连接池使用长连接操作 Redis。频繁的短连接会导致 Redis耗费大量时间在连接的创建和断开上,并且TCP三次握手和四次挥手也会增加访问延迟。在使用长连接时需要注意设置合理的参数,连接数不能过多,长时间不操作 Redis 时要有释放连接资源的机制。

7、【建议】key规范命名。一个好的key命名应由业务名为前缀、英文半角冒号进行分隔、数据类型作为结尾,如user:uid:1:string。禁止使用单双引号、换行符及其它转义字符。好的命名可加强数据可读性便于进行问题定位和寻找数据

8、建议key命名不要过长。在见名知意的前提下尽量简短,建议不超过44字节,避免因为大量key名过长占用额外的内存。通过object encoding keyname命令可以看到当字符超过44字节的时候编码由embstr转为了raw。它们的区别在于embstr是分配一块连续的内存空间,而raw会分配两次

9、【建议】避免存储bigkey。由于Redis 是单线程执行读写指令(即便Redis 6依然如此),如果对bigkey 进行读写操作都会阻塞主线程,影响Redis的性能。string类型建议控制在10K以内(短篇小说也才几十K),hash、list、set、zset类型元素个数建议不要过万。如果业务需要,建议通过压缩方式减小数据大小。

10、【建议】控制key的生命周期。把Redis仅当作缓存使用,建议根据业务需求尽可能对每一个Key都设置过期时间,避免无效数据堆积占用大量内存。在进行过期时间设置时要注意集中过期问题,将过期时间打散,避免缓存雪崩。

11、【建议】控制Key的总数量。单个实例包含的Key数量建议控制在1千万内,单实例的键个数过大,可能导致过期键回收不及时。

12、【建议】非必要仅使用DB0。如果考虑业务拆分建议部署多个实例进行隔离。在一个连接上操作多个db时,会因为SELECT切换带来额外消耗。并且Redis Cluster只支持db0,如果后期进行架构调整,会增大迁移成本。

13、【建议】选择合适的数据类型。Redis提供了丰富的数据类型,需要根据业务场景选择合适的类型。Redis自身为了节约内存资源,一种数据类型可能对应多种数据结构,如Hash类型在元素数量比较少时采用压缩列表(ziplist)存储,在存储数据较多时会转换为哈希表。建议在不确定复杂数据类型优于 String时,避免使用复杂数据类型。

14、【建议】冷热数据分离。Redis作为高性能缓存应该尽量多保存业务热点数据,对于低频冷数据可以使用 MySQL、MongoDB 等基于磁盘的存储方式,节约内存成本,提升性能。

15、【建议】在业务系统实现服务熔断或请求限流。通过熔断机制防止缓存服务异常引发数据库甚至整个业务系统连锁反应。为了减少熔断影响还可以进一步配置请求限流,避免大量并发请求压力传递到数据库层。

16、【参考】数据一致性验证机制。对于读写缓存或者只读缓存设计不同的数据一致性验证机制,避免缓存与数据库信息不一致。

17、【参考】选择合适的架构。如果业务读请求量较大,可以采用部署多个从库的方式结合哨兵实现高可用的读写分离,让从库分担读压力,进而提升性能。如果业务写请求量很大,单个Redis实例已无法支撑,建议使用分片集群。


三、Redis使用规范(运维侧)

1、强制限制高危命令的使用。可以采用重命名方式将高危命令进行修改,限制客户端直接使用,降低主线程阻塞风险。

2、强制开启lazy-free机制。对于无法避免的BigKey,采用异步处理,可以在最大程度上避免对主线程的影响。对于FLUSHDB和FLUSHALL操作也需要通过 ASYNC异步执行。

3、强制做好Redis资源隔离。建议按照业务线部署Redis,可以避免业务相互影响以及单实例膨胀问题,并且在发生故障时降低影响面,且有助于快速恢复。

4、强制从库必须开启只读模式避免从库写入数据导致主从数据不一致。Redis 4.0之前还存在从库写入有过期时间的数据但是不会被清理的问题,容易造成从库内存泄露。

5、强制保证高可用架构。为了避免服务器宕机及其它可能发生的服务不可用风险,Redis应部署为主从+哨兵模式,并且节点各自独立,避免交叉部署。

6、强制做好资源监控。做好服务器基础资源(CPU、内存、带宽、磁盘等)与实例运行时重要指标监控(节点状态、主从同步、内存占用、慢日志、key数量等),触发阈值有报警机制。

7、强制合理的内存控制。根据业务预估数据量为每个实例配置合理的max memory,为系统预留至少30%最大可用内存。避免Redis内存持续膨胀,过大的实例在主从全量同步及RDB备份时都会增加运维难度。

8、建议关闭数据持久化。把Redis仅作为缓存使用,对于丢失数据不敏感的业务可以关闭数据持久化功能,避免持久化大量数据时产生的磁盘IO影响Redis性能。

9、建议设置过期数据淘汰策略。结合业务特点设置过期数据淘汰策略,避免内存中存放大量无效数据。

10、【建议】开启密码认证。不同业务线应配置不同的认证密码,提升安全性。

11、【建议】monitor命令控制时长。随着monitor命令执行时间增长,数据会不断积压在输出缓冲区,最终导致输出缓冲区溢出,引起服务崩溃。建议仅在定位Redis性能问题时才使用该命令。


评论