如何解决Redis中的热点key问题

Redis中的热点Key问题是指某些特定的Key被频繁访问,导致Redis中某个节点(或实例)承担过高的压力,可能引发性能瓶颈,甚至若缓存承受不住服务压力挂掉后,仍有大量请求时直接打到DB上,由于DB层相对缓存层查询性能更弱,在面临大请求时很容易发生DB雪崩现象,严重影响业务。

1. 什么样的Key被称为热点Key

通常以Key被请求频率来判定,目前没有具体的固定的数值来衡量,但有相关参考标准:

  • QPS集中在特定的Key:如Redis实例的总QPS(每秒查询率)为2W,而其中一个Key的每秒访问量达到了1W以上
  • 带宽使用率 集中在特定的Key:对一个拥有上千个成员且总大小为1MB以上的HASH Key,每秒发送大量的HGETALL操作请求;
  • CPU使用时间占比 集中在特定的Key:对一个拥有数万个成员的Key(ZSET类型)每秒发送大量的ZRANGE操作请求;

2. 解决方案

  • 热点key拆分

热点Key问题是由于某个(或某些)Key被频繁访问,因此最直接的解决方案是破坏热点Key的形成,将热点Key进行逻辑拆分,将一个热点key拆分为多个Key,通过逻辑分片的方式将请求分散到不同的Key上,从而避免集中访问。拆分方式有两种:全量拷贝和切片拷贝。

有些场景可以将热点Key进行全量拷贝,比如主从复制架构下,将hot_key拆分成hot_key1、hot_key_2、hot_key_3等,它们之间的数据是一致的,不同的请求都能访问到全量的数据。

有些场景可以将热点Key进行拆分,hot_key1、hot_key_2、hot_key_3各存储hot_key的一部分数据

实现方式如下:

数据写入时:

  • 将热点 Key 拆分为 key_1key_2key_3 等多个 Key。
  • 访问时通过随机选择、哈希映射等方式确定具体的分片 Key。

数据读取时:

聚合所有分片数据,返回合并后的结果。

  • 使用二级缓存+Redis缓存

使用本地缓存,如利用ehcache、GuavaCache等,甚至是一个HashMap都可以。在发现热Key以后,把热Key加载到系统的JVM中,针对这种热Key请求,会直接从本地缓存中取,而不会直接请求redis;非热点Key直接走Redis缓存。

  • 读写分离

在主从复制模式下,从库会存储主库的所有数据包括热点Key,因此通过主从的读写分离,将读请求负载均衡分发到不同的从节点上,从而降低单节点的压力

  • 高并发优化

对于频繁的写操作如计数器累加等,可以通过批量合并多个请求来减少Redis的访问频率。

  • 限流和降级(兜底方案)

为防止发生热点Key问题时造成服务不可能等严重问题,可在热点Key访问过高时,进行应用限流,限制访问频率,减少对Redis的访问,甚至有必要时返回降级的数据(可通过配置文件自行定义)或空值

3. 如何发现及预防热点Key

  • 根据业务经验进行分析(推荐)

主要根据业务场景进行分析,通过经验来判断哪些Key可能会成为热点Key,比如秒杀活动、演唱会门口、热搜新闻等。但是并不是每个热key都能被准确的预测,如对于电商平台来说,商家什么时候会上架相对火爆的秒杀活动就很难预测了,但是可以借助对不同商家的历史活动的数据分析来做一定的参考。

  • Redis集群监控(依赖于集群,较推荐)

该方案依赖于Redis集群,在Redis集群架构下,查看集群中的哪个Redis出现QPS倾斜,而出现QPS倾斜的实例有极大可能存在热点Key。

  • 使用hotKey监控(不推荐)

该命令为Redis 4.0后新引入的一个指令,需要扫描所有的Key,如果Key较多的话执行时间会很长,效率低下。

  • 客户端监控和收集(推荐)

这个方式就是在操作Redis之前,加入一行代码进行数据统计,异步上报行为,如类似日志采集,将单次Redis命令的操作/结果/耗时等统计,异步消息发送给采集消息队列,缺点就是对代码造成入侵,一般可以交给中间件加在自己包的redis二方包中;如果有做的好一点的Daas平台,可以在proxy层做监控,业务无需感知,统一在Daas平台查看redis监控;

相关推荐
月光水岸New2 小时前
Ubuntu 中建的mysql数据库使用Navicat for MySQL连接不上
数据库·mysql·ubuntu
狄加山6752 小时前
数据库基础1
数据库
我爱松子鱼2 小时前
mysql之规则优化器RBO
数据库·mysql
chengooooooo2 小时前
苍穹外卖day8 地址上传 用户下单 订单支付
java·服务器·数据库
Rverdoser3 小时前
【SQL】多表查询案例
数据库·sql
Galeoto3 小时前
how to export a table in sqlite, and import into another
数据库·sqlite
希忘auto4 小时前
详解Redis在Centos上的安装
redis·centos
人间打气筒(Ada)4 小时前
MySQL主从架构
服务器·数据库·mysql
leegong231114 小时前
学习PostgreSQL专家认证
数据库·学习·postgresql
喝醉酒的小白4 小时前
PostgreSQL:更新字段慢
数据库·postgresql