Redis【HotKey问题】
一、简介
Redis单个实例,突然出现大量请求访问该HotKey,导致流量过于集中,达到Redis单实例处理阈值,从而导致RedisCPU使用率100%,或者网卡流量达到上限等。影响系统稳定性,更严重将导致服务器宕机。
对于Redis单实例,业界认为理论极限OPS为10W左右,实际可能根据实际情况有偏差。
二、如何发现HotKey
2.1、预估业务流量
根据业务系统上线的一些活动和功能,我们是可以在某些场景下提前预估热 Key
的出现的,比如业务需要进行一场商品秒杀活动,秒杀商品信息和数量一般都会缓存到 Redis
中,这种场景极有可能出现热 Key
问题的。
【优点】:简单,凭经验发现热 Key
,提早发现提早处理;
【缺点】:没有办法预测所有热 Key
出现,比如某些热点新闻事件,无法提前预测。
2.2、客户端监控
一般我们在连接 Redis
服务器时都要使用专门的 SDK(比如:Java
的客户端工具 Jedis
、Redisson
),我们可以对客户端工具进行封装,在发送请求前进行收集采集,同时定时把收集到的数据上报到统一的服务进行聚合计算。
【优点】:方案简单
【缺点】:
1、对客户端代码有一定入侵,或者需要对 SDK
工具进行二次开发。
2、没法适应多语言架构,每一种语言的 SDK
都需要进行开发,后期开发维护成本较高。
2.3、代理层监控
如果所有的 Redis
请求都经过 Proxy
(代理)的话,可以考虑改动 Proxy
代码进行收集,思路与客户端基本类似。
【优点】:对使用方完全透明,能够解决客户端 SDK
的语言异构和版本升级问题;
【缺点】:1、开发成本比客户端高;
2、并不是所有的 Redis
集群架构中都有 Proxy
代理(使用这种方式必须要部署 Proxy
)。
2.4、Redis自带命令
2.4.1、hotkeys参数
Redis
在 4.0.3
版本中添加了 hotkeys 查找特性,可以直接利用 redis-cli --hotkeys
获取当前 keyspace
的热点 key
,实现上是通过 scan + object freq
完成的。
【优点】:无需进行二次开发,能够直接利用现成的工具
【缺点】:1、由于需要扫描整个 keyspace
,实时性上比较差
2、扫描时间与 key
的数量正相关,如果 key
的数量比较多,耗时可能会非常长。
2.4.2、moniter命令
monitor
命令可以实时抓取出 Redis
服务器接收到的命令,通过 redis-cli monitor
抓取数据,同时结合一些现成的分析工具,比如 redis-faina,统计出热 Key。
【优点】:无需进行二次开发,能够直接利用现成的工具
【缺点】:该命令在高并发的条件下,有内存增暴增的隐患,还会降低 Redis
的性能
2.5、依靠大厂的基建能力
其实各大云厂商都有提供发现hotkey,bigkey的能力,包括各大厂的基架也都有对应的Redis监控工具,可以对hotkey和bigkey进行发现。
1、多级缓存
Key
以后,把热 Key
加载到系统的 JVM
中。后续针对这些热 Key
的请求,会直接从 JVM
中获取,而不会走到 Redis
层。这些本地缓存的工具很多,比如 Ehcache
,或者 Google Guava
中 Cache
工具,或者直接使用 HashMap
作为本地缓存工具都是可以的。Key
进行本地缓存,需要防止本地缓存过大,影响JVM Heap空间;Redis
集群读写数据一致性问题。通过前面的分析,我们可以了解到,之所以出现热
Key
,是因为有大量的对同一个 Key
的请求落到同一个 Redis
实例上,如果我们可以有办法将这些请求负载到不同的实例上,防止出现流量倾斜的情况,那么热 Key
问题也就不存在了。
那么如何将对某个热 Key
的请求打散到不同实例上呢?我们就可以通过热 Key
备份的方式,基本的思路就是,我们可以给热 Key
加上前缀或者后缀,把一个热 Key
的数量变成 Redis
实例个数 N
的倍数 M
,从而由访问一个 Redis
Key
变成访问 M
个 Redis
Key
。 M
个 Redis
Key
经过分片分布到不同的实例上,将访问量均摊到所有实例
- 数据一致性:
1、多个Redis节点之间数据的一致性无法保证,数据同步的时候会存在部分数据不一致性的情况
2、如果存在数据更新的情况,需要同时更新所有Redis节点,此处也会有数据不一致的情况