Redis中的HotKey如何解决

2023-02-07 18:01:58 浏览数 (1)

对于三高系统,Redis是必须/必需的,当并发高到一定的程度就可能会出现HotKey的问题,今天我们来看下Redis中的HotKey如何解决。

什么是HotKey

在较短的时间内,海量请求访问一个Key,这样的Key就被称为HotKey。

HotKey的危害

  • 海量请求在较短的时间内,访问一个Key,势必会导致被访问的Redis服务器压力剧增,可能会将Redis服务器击垮,从而影响线上业务;
  • HotKey过期的一瞬间,海量请求在较短的时间内,访问这个Key,因为Key过期了,这些请求会走到数据库,可能会将数据库击垮,从而影响线上业务。(这是缓存击穿问题)

HotKey如何解决

HotKey如何解决是一个比较宽泛的问题,涉及到多个方面,我们一个个来看。

Redis部署

通常来说,Redis有两种集群形式:数据分片集群、主从 哨兵集群,其实这两种集群形式或多或少的都一定程度上缓解了HotKey的问题。

主从 哨兵集群

如果我们采用单主:

  • 所有的读请求都会打在仅有的一个Redis服务器,都不用管Key是什么,只要并发一高,就会导致Redis服务器压力剧增;
  • 一旦仅有的一个Redis服务器挂了,就没有第二个Redis服务器顶上去了,无法继续提供服务。

如果我们采用主从 哨兵集群:

  • 读请求会被分散到Master节点或者多台Slave节点,将请求进行了初步的分散;
  • Master节点挂了,Slave节点会升级为新的Master节点,继续提供服务。

数据分片集群

Key被分散在了不同的Redis节点,将请求进行了进一步的分散。

如果采用数据分片集群,同时也会部署主从 哨兵,这样又有了主从 哨兵集群的特性:

  • 读请求会被分散到Master节点或者多台Slave节点,将请求进行了初步的分散;
  • Master节点挂了,Slave节点会升级为新的Master节点,继续提供服务。

画外音:我以前一直以为大部分公司都已经采用了数据分片集群,其实不然,某个我认为不差钱的公司,在2021年采用的还是主从 哨兵集群,出了问题,才转变成数据分片集群,我到我们公司一瞧,才发现我们公司也是主从 哨兵集群。

隔离

不同的业务分配不同的Redis集群,不要将所有的业务都“混杂”在一个Redis集群。

只要可以做到集群 隔离,在一定程度上就已经避免了HotKey,但是对于超高并发的系统来说,可能还有点不够,所以才会有下面的更进一步的措施。

如何应对HotKey

这个问题,可以拆分成三个子问题:如何发现HotKey、如何通知HotKey的产生、如何对HotKey进行处理。

如何发现HotKey

如何发现HotKey的前提是知道每个Key的使用情况,并进行统计,所以这又拆成了两个更小的子问题:如何知道每个Key的使用情况,如何进行统计。

如何知道每个Key的使用情况

谁最清楚知道每个Key的使用情况,当然是客户端、代理层,所以我们可以在客户端或者代理层进行埋点。

客户端埋点

在客户端请求Redis的代码中进行埋点。

优点:

  • 实现较为简单
  • 轻量级
  • 几乎没有性能损耗

缺点:

  • 进行统一管理较为麻烦:如果想开启或者关闭埋点、上报,会比较麻烦
  • 升级、迭代较为麻烦:如果埋点、上报方式需要优化,就需要升级Jar包,再找一个黄道吉日进行发布
  • 客户端会有一定的压力:不管是实时上报使用情况,还是准实时上报使用情况,都会对客户端造成一定的压力
代理层埋点

客户端不直接连接Redis集群,而是连接Redis代理,在代理层进行埋点。

优点:

  • 客户端没有压力
  • 对客户端完全透明
  • 升级、迭代比较简单
  • 进行统一管理比较简单

缺点:

  • 实现复杂
  • 会有一定的性能损耗:代理层需要转发请求到真正的Redis集群
  • 单点故障问题:需要做到高可用,更复杂
  • 单点热点问题:代理层本身就是一个热点,需要分散热点,更复杂
如何上报每个Key的使用情况

我们在客户端或者代理层进行了埋点,自然是由它们上报每个Key的使用情况,如何上报又是一个小话题。

实时/准实时
  • 实时上报:每次请求,都进行上报
  • 准实时上报:积累一定量或者一定时间的请求,再进行上报
是否预统计

如果采用准实时上报,在客户端或者代理层是否对使用情况进行预统计:

  • 进行预统计:减少上报的数据量,减轻统计的压力,自身会有压力
  • 不进行预统计:上报的数据量比较多,自身几乎没有压力
如何统计

不管如何进行上报,使用情况最终都会通过Kafka,发送到统计端,这个时候统计端就来活了。 一般来说,这个时候会借助于大数据,较为简单的方式:Flink开一个时间窗口,消费Kafka的数据,对时间窗口内的数据进行统计,如果在一个时间窗口内,某个Key的使用达了一定的阈值,就代表这是一个HotKey。

如何通知HotKey的产生

经过上面的步骤,我们已经知道了某个HotKey产生了,这个时候就需要通知到客户端或者代理层,那如何通知HotKey的产生呢?

  • MQ:用MQ通知客户端或者代理层HotKey是什么
  • RPC/Http:通过RPC/Http通知客户端或者代理层HotKey是什么
  • 配置中心/注册中心指令:既然遇到了HotKey的问题,并且想解决,那基本上是技术实力非常强大的公司,应该有非常完善的服务治理体系,此时,可以通过配置中心/注册中心下发指令到客户端或者代理层,告知HotKey是什么

如何处理HotKey

客户端或者代理层已经知晓了HotKey产生了,就自动开启一定的策略,来避免HotKey带来的热点问题:

  • 使用本地缓存,不至于让所有请求都打到Redis集群
  • 将HotKey的数据复制多份,分散到不同的Redis节点上

在实际开发中,可能在很大程度上,都不会有埋点、上报、统计,通知、策略自动开启,这一套比较完善的Redis HotKey解决方案,我们能做到的就是预估某个Key可能会成为热点,就采用本地缓存 复制多份HotKey数据的方式来避免HotKey带来的热点问题。我们还经常会因为偷懒,所以设计了一个大而全的Key,所有的业务都从这个Key中读取数据,但是有些业务只需要其中的一小部分数据,有些业务只需要另外一小部分数据,如果不同的业务读取不同的Key,又可以将请求进行分散,这是非常简单,而且有效的方式。

0 人点赞