优质博文:IT-BLOG-CN
一、开发规范
【1】弱依赖检查与线下确认:Redis
必须是弱依赖,即Redis
宕机不影响业务。包括超时检查。
【2】是否当存储使用检查:Redis
不能作为存储设备来使用,只能作为缓存或状态等场景来使用。存储优先使用本地缓存。
【3】超时时间检查与线下确认:Redis
使用需要设置超时时间。如果超时,对应的策略和方案是什么。
【4】无状态检查:Redis
同一个Key
不能被不同的应用,不同的场景使用。谁生产,谁消费的原则。
【5】同步锁检查:优先使用集团框架提供的分布式锁。
【6】Key
检查:Key
的唯一性是否存在明显问题,与其他场景和应用的重名的可能。Key
的长度,尽可能的小于128
字节,禁止超过1024
简洁性
保证语义的前提下,控制key
的长度,当key
较多时,内存占用也不容忽视可读性和可管理性 以业务名(或数据库名)为前缀(防止key冲突),用冒号分隔,比如业务名:表名:id
不要包含特殊字符,反例:包含空格、换行、单双引号以及其他转义字符需要规范(car
+应用名+业务名+具体id
)
【7】审批记录检查:是否已经在审批记录conf
完整记录,包括审批人。
二、场景使用
合理使用数据结构: Redis
支持的数据库结构类型较多:字符串String
,哈希Hash
,列表List
,集合Set
,有序集合Sorted Set
, Bitmap
, HyperLogLog
和地理空间索引geospatial
redis
命令
需要根据业务场景选择合适的类型,常见的如:
【1】String
可以用作普通的K-V
、计数类;
【2】Hash
可以用作对象如商品、经纪人等,包含较多属性的信息;
【3】List
可以用作消息队列(不推荐)、粉丝/关注列表等;
【4】Set
可以用于推荐;
【5】Sorted Set
可以用于排行榜等;
三、键值设计
key
设计:
【1】可读性和可管理性【建议】
☑️ 以业务名(或数据库名)为前缀(防止key
冲突),用冒号分隔。
☑️ 应用名:表名:id
。
【2】简洁性,key
长度适中【建议】
☑️ 保证语义的前提下,控制key
的长度,当key
较多时,内存占用也不容忽视。
eg:user:{uid}:friends:messages:{mid}
简化为u:{uid}:fr:m:{mid}
。
【3】不要包含特殊字符【强制】
☑️ 禁止包含特殊字符如空格,换行,单双引号,其他转义字符。
【4】Key
个数限制【强制】
☑️ 由于Redis Rehash
机制,实例Key
数量达到一定值rehash
操作时,需要有一定量空闲内存资源,如key
达到134217728
,rehash
需要有2gb
空闲内存资源,达到268435456
时,rehash
需要有4gb
空闲内存资源。如果没有组够的内存资源rehash
时会发生Key
剔除(数据丢失/程序超时/甚至引起切换)。
单实例key
个数达到134217728
已经很大了,实例元素过大对于后续分析rdb
遍历大key
时会非常耗时。
四、value
设计
【1】拒绝bigkey
(防止网卡流量、慢查询)
☑️ 防止网卡流量、慢查询,string
类型控制在10KB
以内,hash
、list
、set
、zset
元素个数不要超过5000
。
☑️ 非字符串的bigkey
,不要使用del
删除,使用hscan
、sscan
、zscan
方式渐进式删除,同时要注意防止bigkey
过期时间自动删除问题(例如一个200
万的zset
设置1
小时过期,会触发del
操作,造成阻塞,而且该操作不会出现在慢查询中(latency
可查))
☑️ credis
页面,群集所有者可以通过unlink
异步清理或小批量迭代清理(或提事件给DBA
来处理)
【2】一定要设置过期时间,当实例写满,根据volatile-lru
淘汰老的数据
☑️ redis
只是缓存,不能当成数据库来用。不设置过期时间,redis
实例大小会一直无限增长,会出现机器内存耗尽、故障恢复耗时特别长等问题。
☑️ 建议使用expire
设置过期时间(条件允许可以打散过期时间,防止集中过期),不过期的数据重点关注idletime
(该命令返回的是当前键从上一次访问到现在经过的时间(单位,秒))
☑️ DBA
会定期对redis
集群中过期时间超过1
年的数据做告警处理。
五、命令使用
【1】禁用KEYS
正则匹配,可用SCAN
代替
☑️ 禁止线上使用keys
、flushall
、flushdb
等,通过redis
的rename
机制禁掉命令,或者使用scan
的方式渐进式处理。
【2】O(N)
命令关注N
,控制集合元素尽可能小
☑️ hgetall/lrange/smembers/zrange
等在集合包含元素个数较少的情况下使用。
☑️ 若规模较大,有遍历需求,可用HSCAN/SSCAN/ZSCAN
渐进式遍历。
【3】合理使用select
☑️ redis
的多数据库较弱,使用数字进行区分,很多客户端支持较差,同时多业务用多数据库实际还是单线程处理,会有干扰。
【4】Redis
事务支持较弱,不建议过多使用
☑️ redis
的事务功能较弱(不支持回滚),而且集群版本(自研和官方)要求一次事务操作的key
必须在一个slot
上(可以使用hashtag
功能解决)
【5】线上禁止使用monitor
命令
☑️ 禁止生产环境使用monitor
命令,monitor
命令在高并发条件下,会存在内存暴增和影响Redis
性能的隐患。
【6】使用批量操作提高效率
☑️ 原生命令:例如mget
、mset
。
☑️ 非原生命令:可以使用pipeline
提高效率。
☑️ 但要注意控制一次批量操作的元素个数(例如500
以内,实际也和元素字节数有关)。
注意两者不同:
1、原生是原子操作,pipeline
是非原子操作。
2、pipeline
可以打包不同的命令,原生做不到。
3、pipeline
需要客户端和服务端同时支持。
六、数据保存
【1】容量合理评估
☑️ 在系统设计阶段,需要考虑当前redis
集群的容量是否足够,设置合理的大小和过期时间
1、内存使用率保持在[50%~85%]
之间。
2、使用率<50%
需要考虑缩容。
3、使用率>85%
需要考虑扩容。
【2】冷热数据分离
☑️ 虽然Redis
支持持久化,但是Redis
的数据存储全部都是在内存中的,成本昂贵。
☑️ 建议根据业务只将高频热数据存储到Redis
中【QPS
大于5000
】,对于低频冷数据可以使用MySQL
/ElasticSearch
/MongoDB
等基于磁盘的存储方式,不仅节省内存成本,而且数据量小在操作时速度更快、效率更高。
【3】不同的业务数据要分开存储
☑️ 不要将不相关的业务数据都放到一个Redis
实例中,建议新业务申请新的单独实例。
☑️ 因为Redis
为单线程处理,独立存储会减少不同业务相互操作的影响,提高请求响应速度;同时也避免单个实例内存数据量膨胀过大,在出现异常情况时可以更快恢复服务。
【4】必须要存储的大文本数据一定要压缩后存储
☑️ 对于大文本【一般超过500
字节】写入到Redis
时,建议要压缩后存储。
☑️ 大文本数据存入Redis
,除了带来极大的内存占用外,在访问量高时,很容易就会将网卡流量占满,进而造成整个服务器上的所有服务不可用,并引发雪崩效应,造成各个系统瘫痪