Redis【HotKey问题】

发布时间 2023-10-27 16:46:30作者: 木乃伊人

一、简介

       Redis单个实例,突然出现大量请求访问该HotKey,导致流量过于集中,达到Redis单实例处理阈值,从而导致RedisCPU使用率100%,或者网卡流量达到上限等。影响系统稳定性,更严重将导致服务器宕机。

         对于Redis单实例,业界认为理论极限OPS为10W左右,实际可能根据实际情况有偏差。

二、如何发现HotKey

       2.1、预估业务流量

              根据业务系统上线的一些活动和功能,我们是可以在某些场景下提前预估热 Key 的出现的,比如业务需要进行一场商品秒杀活动,秒杀商品信息和数量一般都会缓存到 Redis 中,这种场景极有可能出现热 Key 问题的。

              【优点】:简单,凭经验发现热 Key,提早发现提早处理;

              【缺点】:没有办法预测所有热 Key 出现,比如某些热点新闻事件,无法提前预测。

       2.2、客户端监控

               一般我们在连接 Redis 服务器时都要使用专门的 SDK(比如:Java 的客户端工具 JedisRedisson),我们可以对客户端工具进行封装,在发送请求前进行收集采集,同时定时把收集到的数据上报到统一的服务进行聚合计算。

               【优点】:方案简单

               【缺点】:

                                 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 GuavaCache 工具,或者直接使用 HashMap 作为本地缓存工具都是可以的。
                    注意:使用本地缓存需要注意两个问题
                               1、如果对热 Key 进行本地缓存,需要防止本地缓存过大,影响JVM Heap空间;
                               2、需要处理本地缓存和 Redis 集群读写数据一致性问题。
                2、负载均衡                      

通过前面的分析,我们可以了解到,之所以出现热

Key,是因为有大量的对同一个 Key 的请求落到同一个 Redis 实例上,如果我们可以有办法将这些请求负载到不同的实例上,防止出现流量倾斜的情况,那么热 Key 问题也就不存在了。

那么如何将对某个热 Key 的请求打散到不同实例上呢?我们就可以通过热 Key 备份的方式,基本的思路就是,我们可以给热 Key 加上前缀或者后缀,把一个热 Key 的数量变成 Redis 实例个数 N 的倍数 M,从而由访问一个 Redis Key 变成访问 MRedis KeyMRedis Key 经过分片分布到不同的实例上,将访问量均摊到所有实例

                     问题: 
                      浪费Redis内存空间:可以通过配置中心设置一个开关,当开关打开时才会访问临时的hotkey节点;
                数据一致性:

1、多个Redis节点之间数据的一致性无法保证,数据同步的时候会存在部分数据不一致性的情况

2、如果存在数据更新的情况,需要同时更新所有Redis节点,此处也会有数据不一致的情况