一 现象
某个业务最近2个月每月1号凌晨0点都有业务高峰,但是业务所使用的 Redis 服务 cpu 负载100% ,无法对外提供服务进而影响整体业务访问。
二 分析
2.1 问题分析
因为该业务使用的是云Redis ,我们通过监控看 CPU,QPS ,带宽。
出现问题时系统的QPS 大约为 1200 左右,但是对应时刻的出口带宽竟然达到500MB/s ,猜测该业务使用的Redis 有bigkey。
2.2 验证猜测
因为对应的版本暂不支持日志审计功能。让驻场的同学抓取Redis的统计数据,如下
从统计数据中可以看到top 5 的key 均为大于1MB的可以,而且 第一个hash 类型的key 里面有10w级别的元素。因为Redis的单线程模型,0点时刻业务请求大量访问这些大key 势必造成 CPU 飙高,网卡流量暴涨。
2.3 解决
原因分析到位,剩下的就好办了,对于hash类型的结构,让客户侧的开发对打 key 进行拆分打散。优化之后的单个key 大约88Byte 。等9月1号凌晨观察效果。
三 Redis的 bigkey 有哪些影响
上面分析一个 bigkey的案例,接下来我们看看bigkey到底带来哪些副作用。bigkey 顾名思义是 value 占用的内存空间比较大的key,对于redis而言存在两种类型 :
- 字符串类型:value 大小大于特点值比如 5KB 的string 类型的key。
- 非字符串/集合类型: 比如存储非常多元素的hash, set ,zset,list类型,如本文案例的存储情况。
对于Redis的维护人员而言,bigkey就是 一个不稳定因素,时不时带稳定性风险。
3.1 影响性能
因为 Redis 单线程的工作机制,主线程处理所有key的增删改查。对bigkey的操作耗时增加将阻塞主线程处理其他业务请求,进而影响整体吞吐量。
3.2 影响带宽
前面的案例即是一个例子,单个key 7MB ,如果每秒100次查询,则带来700MB 的带宽,虽然现在大部分是万兆网卡,业务请求量再大一些,网卡也有被打满的风险。
3.3 数据倾斜
对于分片的redis集群,存在bigkey 会导致单个分片数据量远大于其他节点,整体不均衡。如果一个分片空间容量满了,对系统造成不可访问,而且也不能随意扩容,因为不拆分key的情况下扩容,单个分片还是存在数据倾斜。更惨的是,数据量比较大,那么访问就增加,容易形成热点。热点不都是因为数据倾斜导致,数据倾斜会大概率导致热点。
3.4 影响主从同步
Redis Server 的输出大小通常是不可控制的。存在bigkey的时候,就会产生体积庞大的返回数据。另外也有可能因为执行了太多命令,导致产生返回数据的速率超过了往客户端发送的速率,导致服务器堆积大量消息,从而导致输出缓冲区越来越大,占用过多内存,甚至导致系统崩溃。Redis 通过设置client-output-buffer-limit 来保护系统安全。
此时如果主从配置 sentinel,sentinel 会让 slave 继续向 master 发起全量同步请求,然后 buffer 又溢出同步失败,如此反复,会形成复制风暴,这会耗费 master 大量的 CPU、内存、带宽资源,也会让 master 产生阻塞的风险。
案例 https://blog.csdn.net/damanchen/article/details/101075757
四 如何解决大key?
其实就是一个字 "拆"。
- 对于字符串类型的key,我们通常要在业务层面将value的大小控制在10KB左右,如果value确实很大,可以考虑采用序列化算法和压缩算法来处理,推荐常用的几种序列化算法:Protostuff、Kryo或者Fst。
- 对于集合类型的key,我们通常要通过控制集合内元素数量来避免bigKey,通常的做法是将一个大的集合类型的key拆分成若干小集合类型的key来达到目的。
来自 yangyidba公众号