大key
定义
- string类型的key值大于10kb
- list,set,zset,hash的成员个数超过5000
- list、set、zset、hash的成员数量虽然只有1000个但这些成员的value总大小为100MB(成员体积过大)
带来的问题
- 对redis的请求变慢
- Redis内存不断变大导致OOM,或达到maxmemory值引发写阻塞或重要key被逐出
- Redis集群中某个node内存远超其他node
- 由于对大key的请求很慢,容易造成请求的阻塞,在微服务架构中下容易造成服务雪崩
- 删除一个key很耗时,容易造成主节点阻塞,从而主从切换
产生原因
- 存放不合理,存储了不适合存放在内存中的数据,如用key存放音频视频这一类大体积二进制文件
- 设计不合理,造成个别key中成员太多
- 未定期清理数据,没有设置过期时间,造成了如hash类型中key中的成员不断增加
解决方法
1.查找
- 知道哪个key有问题
debug key-name,对key进行分析并返回分析结果;
STRLEN(string),HLEN(hash),SCARD(set),ZCARD(zset),LLEN(list)返回成员长度; - 不知道哪个key有问题
redis-cli bigkeys,仅能输出最大key,如果想进行范围查询,比如找出全部成员数量超过10的hash是做不到的
2.处理
- 拆分:如将一个成员很多的hash拆分为多个hash
- 删除:使用UNLINK进行异步删除,否则使用del可能造成阻塞
热key
定义
- 某个key接收到的访问次数显著高于其他key时,称之为热key
带来的问题
- 大量请求直接打过来,服务器可能会扛不住,造成缓存击穿从而直接打挂后端存储(数据库),影响其他使用后端存储的服务
- 可能使得redis集群失去意义,redis集群中各node流量不均衡造成redis集群的分布式优势无法被利用,一个分片负载很高而其他分片十分空闲
产生原因
- 流量陡增,如出现某款爆款商品等
解决方法
1.查找
redis-cli hotkeys用来分析热key,该参数能够返回所有key被访问的次数,使用hotkeys的前提条件是将redis-server的maxmemory-policy参数设置为LFU
2.处理
- 复制:在使用redis集群时,可以将热key复制多份,每个redis节点上存放一份,这样不存在请求的重定向使得压力全部定向到单个节点,能够有效减轻单节点的压力。缺点是要进行复制的话只能在代码层手动操作,而且复制多份存放后会存在数据一致性问题。因此复制方案只能用于临时解决线上问题。
- 读写分离:热key多数是读热key的操作,读写分离能够保证从节点中数据的一致性,并且能够轻松的横向扩展,能够有效地分散压力,只是有点浪费资源,因为读写分离每个从节点上存的都是一样的数据。
- 多级缓存:当热key数量不多,比如电商平台促销活动,热key都集中在少部分key上面,为此做读写分离增加机器性价比不高,使用多级缓存是个不错的解决方法。具体实现思路两种:
①本地缓存:redis和业务服务器之间增加一个中间层(proxy),专门用来进行热key探查,这个proxy专门用来监视redis来统计达到预设的热key阈值的key,统计好后推送给业务服务器,让业务服务器存在本地缓存;
②单独缓存:将proxy探查到的热key推送到单独的一个缓存热key的redis上去,如果扛不住,热key服务器再横向扩容,当然这个方案也是单独增加了服务器节点去处理热key的,除非保证系统中经常会有热key出现,不然的使用本地缓存性价比更高。
使用多级缓存会存在一个问题,因为每次推送之间有时间间隔,缓存中的数据和redis中的数据不是呈现强一致性的,而是呈现最终一致性的。这种代价也是不得不接受的,在使用缓存的时候注意不要拿缓存做逻辑,只用来做查询即可。