概要
在实际开发过程中,从性能或者规范的角度考虑,都需要给团队的成员制定使用redis的使用规范。防止出现例如,key的定义五花八门,危险命令代码中随便使用等情况。
规范与建议
1.1 规范Key的格式
“平台缩写“+“:”+“项目名”+“:”+“业务含义” 例如:GW:TRADE:USERID GW是新网关,TRADE是交易项目,USERID为业务ID。“:”-作为key分隔符,方便客户端工具作为目录分级
1.2 禁止bigkey、hot bigkey
bigkey 通常会导致内存空间不平衡,超时阻塞,如果 key 较大,redis 又是单线程,操作 bigkey 比较耗时,那么阻塞 redis 的可能性增大。每次获取 bigKey 的网络流量较大,假设一个 bigkey 为 1MB,每秒访问量为 1000,那么每秒产生 1000MB 的流量,对于redis服务依赖的系统本身CPU和IO均是不小的开销
正例: string类型控制在10kb以内、hash、list、set、zset元素个数不要超过10000
1.3 对于必须要存储的大文本数据一定要压缩后存储
对于大文本【超过500字节】写入到Redis时,一定要压缩后存储!大文本数据存入Redis,除了带来极大的内存占用外,在访问量高时,很容易就会将网卡流量占满,进而造成整个服务器上的所有服务不可用,并引发雪崩效应,造成各个系统瘫痪!
1.4 存储的Key建议设置超时时间
如果应用将Redis定位为缓存Cache使用,对于存放的Key一定要设置超时时间!因为若不设置,这些Key会一直占用内存不释放,造成极大的浪费,而且随着时间的推移会导致内存占用越来越大,直到达到服务器内存上限!另外Key的超时长短要根据业务综合评估,而不是越长越好!(某些业务要求key长期有效。可以在每次写入时,都设置超时时间,让超时时间顺延。)
1.5 线上Redis禁止使用Keys正则匹配操作
Redis是单线程处理,在线上KEY数量较多时,操作效率极低【时间复杂度为O(N)】,该命令一旦执行会严重阻塞线上其它命令的正常请求,而且在高QPS情况下会直接造成Redis服务崩溃!如果有类似需求,请使用scan命令代替!
1.6 禁止出现O(N)时间复杂度的命令
目前redis使用的版本是单线程,即便是升级到6.0+,使用多线程,在O(N)型命令使用的情况下,redis服务阻塞、性能急剧下降
正例:
String类型: MSET、MSETNX、MGET
List类型: LPUSH、RPUSH、LRANGE、LINDEX、LSET、LINSERT(LINDEX、LSET、LINSERT 这三个命令谨慎使用)
Hash类型: HDEL、HGETALL、HKEYS/HVALS**(HGETALL、HKEYS/HVALS 谨慎使用**)
Set类型: SADD、SREM、SRANDMEMBER、SPOP、 SMEMBERS、SUNION/SUNIONSTORE、SINTER/SINTERSTORE、SDIFF/SDIFFSTORE
Sorted Set类型: ZADD、ZREM 、ZRANGE/ZREVRANGE、ZRANGEBYSCORE/ZREVRANGEBYSCORE、ZREMRANGEBYRANK/ZREMRANGEBYSCOREd(除前两个命令外,其他命令时间复杂度 O(log(N)+M),需要谨慎使用)
其他常用命令: DEL、KEYS(KEYS谨慎使用)
1.7 生产建议使用db0库
说明:redis - cluster 支持多db,便于维护建议使用db0
1.8 禁止使用短链接连接redis
连接的频繁创建和销毁,会浪费大量的系统资源,连接redis走长连接,并且请确保使用了正确的 Redis 客户端连接池配置,避免连接过大
1.9 禁止作为消息队列使用
严禁将 Redis 当作消息队列使用,Redis 当作消息队列使用,会有容量、网络、效率、功能方面的多种问题,如需要消息队列,可使用高吞吐的 Kafka 或者高可靠的 RocketMQ
1.10 冷热数据分离,不要把所有数据存放在redis中
虽然 Redis支持持久化,但将所有数据存储在 Redis 中,成本非常昂贵。建议将热数据 的数据加载到 Redis 中,低频数据可存储在 Mysql、 ElasticSearch中
1.11 合理分配业务场景到redis不同数据类型
String可以用作普通的K-V、计数类;Hash可以用作对象如商品、经纪人等,包含较多属性的信息;List可以用作消息队列、粉丝/关注列表等;Set可以用于推荐;Sorted Set可以用于排行榜等
1.12 Redis client需要一定的限流/熔断机制,以及指数退避重试机制
机器的故障、redis服务的故障、网络故障等在业务场景中不可避免,建议在代码编写过程中考虑redis错误的异常捕获处理,特别是关键的执行系统
1.13 不建议使用事务
redis 本身已经很快了,如无大的必要,建议捕获异常进行回滚,不要使用事务函数