首页 > 数据库 >发现并处理Redis的大Key和热Key

发现并处理Redis的大Key和热Key

时间:2024-08-14 14:28:37浏览次数:18  
标签:Key 处理 Redis 命令 key 分片 数据

大Key和热Key的定义
名词解释
大Key通常以Key的大小和Key中成员的数量来综合判定,例如:
Key本身的数据量过大:一个String类型的Key,它的值为5 MB。
Key中的成员数过多:一个ZSET类型的Key,它的成员数量为10,000个。
Key中成员的数据量过大:一个Hash类型的Key,它的成员数量虽然只有2,000个但这些成员的Value(值)总大小为100 MB。
热Key通常以其接收到的Key被请求频率来判定,例如:
QPS集中在特定的Key:Redis实例的总QPS(每秒查询率)为10,000,而其中一个Key的每秒访问量达到了7,000。
带宽使用率集中在特定的Key:对一个拥有上千个成员且总大小为1 MB的HASH Key每秒发送大量的HGETALL操作请求。
CPU使用时间占比集中在特定的Key:对一个拥有数万个成员的Key(ZSET类型)每秒发送大量的ZRANGE操作请求。
大白话大Key和热Key

大Key:占用内存比较大的key

热Key:其实热key问题说来也很简单,就是瞬间有几十万的请求去访问redis上某个固定的key,从而压垮缓存服务的情情况。
也是有不少这样的例子。微博举例子,比如XX明星结婚。那么关于XX明星的Key就会瞬间增大,就会出现热数据问题。

大Key和热Key引发的问题
类别说明
大Key客户端执行命令的时长变慢。
Redis内存达到maxmemory参数定义的上限引发操作阻塞或重要的Key被逐出,甚至引发内存溢出(Out Of Memory)。
集群架构下,某个数据分片的内存使用率远超其他数据分片,无法使数据分片的内存资源达到均衡。
对大Key执行读请求,会使Redis实例的带宽使用率被占满,导致自身服务变慢,同时易波及相关的服务。
对大Key执行删除操作,易造成主库较长时间的阻塞,进而可能引发同步中断或主从切换。
热Key占用大量的CPU资源,影响其他请求并导致整体性能降低。
集群架构下,产生访问倾斜,即某个数据分片被大量访问,而其他数据分片处于空闲状态,可能引起该数据分片的连接数被耗尽,新的连接建立请求被拒绝等问题。
在抢购或秒杀场景下,可能因商品对应库存Key的请求量过大,超出Redis处理能力造成超卖。
热Key的请求压力数量超出Redis的承受能力易造成缓存击穿,即大量请求将被直接指向后端的存储层,导致存储访问量激增甚至宕机,从而影响其他业务。
大Key和热Key产生的原因

未正确使用Redis、业务规划不足、无效数据的堆积、访问量突增等都会产生大Key与热Key,如:

  • 大key
    • 在不适用的场景下使用Redis,易造成Key的value过大,如使用String类型的Key存放大体积二进制文件型数据;
    • 业务上线前规划设计不足,没有对Key中的成员进行合理的拆分,造成个别Key中的成员数量过多;
    • 未定期清理无效数据,造成如HASH类型Key中的成员持续不断地增加;
    • 使用LIST类型Key的业务消费侧发生代码故障,造成对应Key的成员只增不减。
  • 热key
    • 预期外的访问量陡增,如突然出现的爆款商品、访问量暴涨的热点新闻、直播间某主播搞活动带来的大量刷屏点赞、游戏中某区域发生多个工会之间的战斗涉及大量玩家等。
快速找出大Key和热Key行
方法优缺点说明
通过redis-cli的bigkeyshotkeys参数查找大Key和热Key优点:方便、快速、安全。
缺点:分析结果不可定制化,准确性与时效性差。
redis-cli提供了bigkeyshotkeys参数能够以遍历的方式分析Redis实例中的所有Key,并返回Key的整体统计信息与每个数据类型中Top1的大Key。以bigkeys为例,其仅能分析并输入六种数据类型(STRING、LIST、HASH、SET、ZSET、STREAM),命令示例为redis-cli -h r-***************.redis.rds.aliyuncs.com -a <password> --bigkeys说明若您只需要分析STRING类型的大key或是找出成员数量超过10个的HASH Key,则bigkeys参数无法直接实现该类需求。
通过Redis内置命令对目标Key进行分析优点:方便、对线上服务影响小。
缺点:返回的Key序列化长度并不等同于它在内存空间中的真实长度,因此不够准确,仅可作为参考。
对不同数据类型的目标Key,分别通过如下风险较低的命令进行分析,来判断目标Key是否符合大Key判定标准。STRING类型:执行STRLEN命令,返回对应Key的value的字节数。LIST类型:执行LLEN命令,返回对应Key的列表长度。HASH类型:执行HLEN命令,返回对应Key的成员数量。SET类型:执行SCARD命令,返回对应Key的成员数量。ZSET类型:执行ZCARD命令,返回对应Key的成员数量。STREAM类型:执行XLEN命令,返回对应Key的成员数量。说明****DEBUG OBJECTMEMORY USAGE命令在执行时需占用较多资源,且时间复杂度为O(N),有阻塞Redis实例的风险,不建议使用。
通过业务层定位热Key优点:可准确并及时地定位热Key。
缺点:业务代码复杂度的增加,同时可能会降低一些性能。
通过在业务层增加相应的代码对Redis的访问进行记录并异步汇总分析。自己的项目业务自己应该是清除,哪块容易出现热key会有一个大致的判断也
通过redis-rdb-tools工具以定制化方式找出大Key优点:支持定制化分析,对线上服务无影响。
缺点:时效性差,RDB文件较大时耗时较长。
Redis-rdb-tools是通过Python编写,支持定制化分析Redis RDB快照文件的开源工具。您可以根据您的精细化需求,全面地分析Redis实例中所有Key的内存占用情况,同时也支持灵活地分析查询。
通过MONITOR命令找出热Key优点:方便、安全。
缺点:会占用CPU、内存、网络资源,时效性与准确性较差。
Redis的MONITOR命令能够忠实地打印Redis中的所有请求,包括时间信息、Client信息、命令以及Key信息。在发生紧急情况时,可以通过短暂执行MONITOR命令并将返回信息输入至文件,在关闭MONITOR命令后,对文件中请求进行归类分析,找出这段时间中的热Key。说明由于MONITOR命令对Redis实例性能消耗较大,非特殊情况不推荐使用MONITOR命令。

之前也有了解过京东的一个开源项目可以进行热key的一个监控

https://gitee.com/jd-platform-opensource/hotkey

介绍

对任意突发性的无法预先感知的热点请求,包括并不限于热点数据(如突发大量请求同一个商品)、热用户(如爬虫、刷子)、热接口(突发海量请求同一个接口)等,进行毫秒级精准探测到。 然后对这些热数据、热用户等,推送到该应用部署的所有机器JVM内存中,以大幅减轻对后端数据存储层的冲击,并可以由客户端决定如何使用这些热key(譬如对热商品做本地缓存、对热用户进行拒绝访问、对热接口进行熔断或返回默认值)。 这些热key在整个应用集群内保持一致性。

核心功能:热数据探测并推送至集群各个服务器

适用场景:

1 mysql热数据本地缓存

2 redis热数据本地缓存

3 黑名单用户本地缓存

4 爬虫用户限流

5 接口、用户维度限流

6 单机接口、用户维度限流

7 集群用户维度限流

8 集群接口维度限流

优化大Key与热Key
类别处理方法
大Key1.对大Key进行拆分
例如将含有数万成员的一个HASH Key拆分为多个HASH Key,并确保每个Key的成员数量在合理范围。在Redis集群架构中,拆分大Key能对数据分片间的内存平衡起到显著作用。
2. 对大Key进行清理
将不适用Redis能力的数据存至其它存储,并在Redis中删除此类数据。
说明:
Redis 4.0及之后版本:您可以通过UNLINK
命令安全地删除大Key甚至特大Key,该命令能够以非阻塞的方式,逐步地清理传入的Key。
Redis 4.0之前的版本:建议先通过SCAN命令读取部分数据,然后进行删除,避免一次性删除大量key导致Redis阻塞。
3.监控Redis的内存水位
接入普罗米修斯(Prometheus)进行集成实现监控
4.对过期数据进行定期清理
堆积大量过期数据会造成大Key的产生,例如在HASH数据类型中以增量的形式不断写入大量数据而忽略了数据的时效性。可以通过定时任务的方式对失效数据进行清理。
说明:在清理HASH数据时,建议通过HSCAN命令配合HDEL命令对失效数据进行清理,避免清理大量数据造成Redis阻塞。
热Key1. 在Redis集群架构中对热Key进行复制
在Redis集群架构中,由于热Key的迁移粒度问题,无法将请求分散至其他数据分片,导致单个数据分片的压力无法下降。此时,可以将对应热Key进行复制并迁移至其他数据分片,例如将热Key foo复制出3个内容完全一样的Key并名为foo2、foo3、foo4,将这三个Key迁移到其他数据分片来解决单个数据分片的热Key压力。
说明: 该方案的缺点在于需要联动修改代码,同时带来了数据一致性的挑战(由原来更新一个Key演变为需要更新多个Key),仅建议该方案用来解决临时棘手的问题。
2. 使用读写分离架构
如果热Key的产生来自于读请求,您可以将实例改造成读写分离架构来降低每个数据分片的读请求压力,甚至可以不断地增加从节点。但是读写分离架构在增加业务代码复杂度的同时,也会增加Redis集群架构复杂度。不仅要为多个从节点提供转发层(如Proxy,LVS等)来实现负载均衡,还要考虑从节点数量显著增加后带来故障率增加的问题。Redis集群架构变更会为监控、运维、故障处理带来了更大的挑战。
3. 使用本地缓存
当监听到热key的时候,可以使用本地缓存,比如使用Guava的LoadingCache

Guava的LoadingCache示例

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

public class LocalCacheForHotKey {

    public static void main(String[] args) {
        // 创建一个本地缓存
        LoadingCache<String, String> cache = CacheBuilder.newBuilder()
               .maximumSize(1000) // 设置缓存的最大容量
               .expireAfterWrite(10, TimeUnit.MINUTES) // 设置数据写入 10 分钟后过期
               .build(new CacheLoader<String, String>() {
                    @Override
                    public String load(String key) {
                        // 从实际的数据源加载数据,如果缓存中没有
                        return loadDataFromSource(key);
                    }
                });

        // 模拟获取热 Key 的值
        try {
            String value = cache.get("hotKey");
            System.out.println("Value for hotKey: " + value);
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

    public static String loadDataFromSource(String key) {
        // 模拟从数据源加载数据的逻辑
        return "Data for " + key;
    }
}

参考:https://help.aliyun.com/zh/redis/user-guide/identify-and-handle-large-keys-and-hotkeys

标签:Key,处理,Redis,命令,key,分片,数据
From: https://blog.csdn.net/yuanmomoya/article/details/141163560

相关文章

  • 对象池模式,处理Boss的投射物攻击
    不使用对象池如果不使用对象池,那么假设一个Boss技能发射10个投射物,那么就会导致每次技能的释放需要创建10个投射物,然后遇到条件进行销毁对象池模式维护一个存储投射物的容器,然后在发射时从容器中取出,当"销毁时"放回容器中。实现方式以发射投射物为例,首先对于投射物创建一个......
  • 变“金点子”为“好应用”,合合信息智能文档处理技术助力大学生探索AI创新边界
    谈“糖”色变、追求养生、低卡生活……这些热门词汇频频在社交媒体上掀起讨论热潮。有这样一批年轻人不但捕捉到了这些词汇背后真实的用户需求,并且正在利用AI技术寻找解决之道。近日,“中国大学生服务外包创新创业大赛”(以下简称“服创大赛”)决赛在江南大学圆满落幕。作为服务......
  • OpenCV(cv::waitKey())
    目录1.函数解析参数返回值2.示例3.说明4.注意事项cv::waitKey()是OpenCV库中的一个函数,用于等待用户的键盘输入。它在处理图像和视频时非常有用,特别是在显示图像窗口时,用于控制图像的显示和响应用户输入。1.函数解析intcv::waitKey(intdelay=0);参数delay:......
  • java几种常见漏洞种类及处理方案
    一、SQLInjection(SQL注入漏洞)1.使用参数化查询(PreparedStatements)参数化查询是防止SQL注入最有效的方法之一。它确保用户输入的数据作为参数传递,而不是作为SQL命令的一部分。在Java中,可以使用PreparedStatement来实现这一点。示例代码:Stringsql="SELECT*FROMusers......
  • redis运维常用命令
    redis运维常用命令命令time查看时间戳与微秒数dbsize查看当前数据库有多少keybgrewriteaof后台进程重写aofbgsave后台保存rdb快照lastsave上次保存时间slaveofmaster-hostport把当前实例设置为master的slaveflushall清空所有......
  • Specified key was too long; max key length is 1000 bytes
    setglobalinnodb_large_prefix=1;setglobalinnodb_file_format=BARRACUDA;--auto-generateddefinitioncreatetablexxx_term(idintauto_incrementprimarykey,namevarchar(255)default''notnull,source_urlvarchar(500)......
  • 掌握图像处理中的颜色识别与形态学变换技术
    形态学变换形态学变换是一种基于形状的图像处理技术,主要应用于二值化图像。它的核心操作包括腐蚀和膨胀,这两者是对立的基本操作。核(结构化元素):核是一个小的矩阵或模板,用于在图像上进行操作。它定义了进行形态学变换时考虑的邻域范围。腐蚀(Erosion):腐蚀操作会缩小图像中目......
  • 并发场景下,缓存失效处理场景
    并发场景下,缓存失效,需要从数据库或下游查询缓存中的数据。若并发流量都请求到下游,导致下游压力较大,可通过如下方式进行处理:importjava.util.concurrent.*;publicclassSingleFlight{privatefinalConcurrentMap<Object,CompletableFuture<?>>cache=newConcurrent......
  • npm报错:request to https://registry.npm.taobao.org failed处理办法
    今天在安装flowise的时候提示npm报错:requestto https://registry.npm.taobao.org failed,reasoncertificatehasexpired看提示是淘宝镜像过期了。找了一下资料,好像是npm淘宝镜像已经从 registry.npm.taobao.org 切换到了 registry.npmmirror.com。旧域名也将于2022......
  • Python 栅格数据处理教程(一)
    本文将介绍通过ArcGISPro的Python模块(arcpy)对栅格数据定义投影及裁剪的方法。1数据来源及介绍降水量数据:国家青藏高原科学数据中心的中国1km分辨率逐月降水量数据集。行政区数据:天地图行政区划数据中的吉林省边界面数据,该数据为GeoJSON格式,可通过QGIS等软件将其转换......