一、前言
相信有一定开发经验的工程师,对于redis中的大key和热key应该不陌生,无论是哪个业务系统,出现这些问题的原因总是惊人的相似,因此,本文会探讨大key和热key产生的原因以及一些常用防范方法。
二、定义
2.1 大key
通常以Key的大小和Key中成员的数量来综合判定,例如:
-
Key本身的数据量过大:一个String类型的Key,它的值为5 MB。
-
Key中的成员数过多:一个ZSET类型的Key,它的成员数量为10,000个。
-
Key中成员的数据量过大:一个Hash类型的Key,它的成员数量虽然只有1,000个但这些成员的Value(值)总大小为100 MB。
2.2 热key
通常以其接收到的Key被请求频率来判定,例如:
-
QPS集中在特定的Key:Redis实例的总QPS(每秒查询率)为10,000,而其中一个Key的每秒访问量达到了7,000。
-
带宽使用率集中在特定的Key:对一个拥有上千个成员且总大小为1 MB的HASH Key每秒发送大量的HGETALL操作请求。
-
CPU使用时间占比集中在特定的Key:对一个拥有数万个成员的Key(ZSET类型)每秒发送大量的ZRANGE操作请求。
三、引发的问题
3.1 大key
下面是大key可能会引发的问题:
-
客户端执行命令的时长变慢。
-
Redis内存达到maxmemory参数定义的上限引发操作阻塞或重要的Key被逐出,甚至引发内存溢出(Out Of Memory)。
-
集群架构下,某个数据分片的内存使用率远超其他数据分片,无法使数据分片的内存资源达到均衡。
-
对大Key执行读请求,会使Redis实例的带宽使用率被占满,导致自身服务变慢,同时易波及相关的服务。
-
对大Key执行删除操作,易造成主库较长时间的阻塞,进而可能引发同步中断或主从切换。
3.2 热key
下面是热key可能会引发的问题:
-
占用大量的CPU资源,影响其他请求并导致整体性能降低。
-
集群架构下,产生访问倾斜,即某个数据分片被大量访问,而其他数据分片处于空闲状态,可能引起该数据分片的连接数被耗尽,新的连接建立请求被拒绝等问题。
-
在抢购或秒杀场景下,可能因商品对应库存Key的请求量过大,超出Redis处理能力造成超卖。
-
热Key的请求压力数量超出Redis的承受能力易造成缓存击穿,即大量请求将被直接指向后端的存储层,导致存储访问量激增甚至宕机,从而影响其他业务。
四、产生的原因
未正确使用Redis、业务规划不足、无效数据的堆积、访问量突增等都会产生大Key与热Key,如:
4.1 大key
-
在不适用的场景下使用Redis,易造成Key的value过大,如使用String类型的Key存放大体积二进制文件型数据;
-
业务上线前规划设计不足,没有对Key中的成员进行合理的拆分,造成个别Key中的成员数量过多;
-
未定期清理无效数据,造成如HASH类型Key中的成员持续不断地增加;
-
使用LIST类型Key的业务消费侧发生代码故障,造成对应Key的成员只增不减。
4.2 热key
-
预期外的访问量陡增,如突然出现的爆款商品、访问量暴涨的热点新闻、直播间某主播搞活动带来的大量刷屏点赞、游戏中某区域发生多个工会之间的战斗涉及大量玩家等。
五、优化措施
5.1 大key
-
对大Key进行拆分,例如将含有数万成员的一个HASH Key拆分为多个HASH Key,并确保每个Key的成员数量在合理范围。在Redis集群架构中,拆分大Key能对数据分片间的内存平衡起到显著作用。
-
对大Key进行清理,将不适用Redis能力的数据存至其它存储,并在Redis中删除此类数据。
-
对过期数据进行定期清理,堆积大量过期数据会造成大Key的产生,例如在HASH数据类型中以增量的形式不断写入大量数据而忽略了数据的时效性。可以通过定时任务的方式对失效数据进行清理。
5.2 热key
-
在Redis集群架构中对热Key进行复制,在Redis集群架构中,由于热Key的迁移粒度问题,无法将请求分散至其他数据分片,导致单个数据分片的压力无法下降。此时,可以将对应热Key进行复制并迁移至其他数据分片,例如将热Key foo复制出3个内容完全一样的Key并名为foo2、foo3、foo4,将这三个Key迁移到其他数据分片来解决单个数据分片的热Key压力。
-
使用读写分离架构,如果热Key的产生来自于读请求,您可以将实例改造成读写分离架构来降低每个数据分片的读请求压力,甚至可以不断地增加从节点。但是读写分离架构在增加业务代码复杂度的同时,也会增加Redis集群架构复杂度。不仅要为多个从节点提供转发层(如Proxy,LVS等)来实现负载均衡,还要考虑从节点数量显著增加后带来故障率增加的问题。Redis集群架构变更会为监控、运维、故障处理带来了更大的挑战。
六、案例
6.1 数据压缩
例如一些数据比较大的业务数据,可以进行数据压缩,需要牺牲一下cpu。
6.2 进行键拆分
列举笔者工作中的场景,例如笔者目前主要从事的港美股证券金融行业,保存在redis中的热点数据,规范是需要根据市场进行区分的。例如键的key需要带市场前缀的,例如港股就是**:HK:**,类似的美股就是**:US:**。
6.3 游标处理
Cursor的优势
使用Cursor可以带来多个优势:
减少内存占用:通过分批获取集合中的元素,可以减少内存消耗。
提高性能:遍历大集合时,使用Cursor可以提高遍历效率。
动态更新:在遍历过程中,如果集合发生变化,Cursor会自动更新,确保遍历的是最新的元素
好了,本期的分享就到这里了,如果有更好的想法,可以一起交流探讨一下。
重点!重点!重点!听说题主开通了公众号:有理唔理,你真的不关注一下嘛!