• 大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中的数据不是呈现强一致性的,而是呈现最终一致性的。这种代价也是不得不接受的,在使用缓存的时候注意不要拿缓存做逻辑,只用来做查询即可。