基于 Redis 内核的热 key 统计实现方案
一、Redis热key介绍
Redis热key问题是指单位时间内,某个特定key的访问量特别高,占用大量的CPU资源,影响其他请求并导致整体性能降低。而且,如果访问热key的命令是时间复杂度较高的命令,会使得CPU消耗变得更加严重;或者,如果访问的热key同时也是一个大key,也可能使得访问流量达到节点所在机器带宽上限。
二、Redis热key常见探测方法
突发的热点新闻、爆款商品、或者促销活动都可能导致访问热key的出现,目前,Redis官方和业界也都有不少热key探测与发现方法。
先通过一个表格整体预览一下当前存在的热key探测方案优缺点
Redis-cli的hotkeys参数
Redis自4.0起在Redis-cli中提供了hotkeys参数来方便用户进行实例级的热key分析功能,Redis-cli通过向Redis-server节点发送scan + object freq命令以遍历的方式分析Redis实例中所有key,然后返回实例中热key信息。
该方式存在以下几个问题:
- 使用该方案的前提条件是需要将Redis-server的淘汰策略maxmemory-policy参数设置为LFU(volatile-lfu或allkeys-lfu)
- 实时性差。由于需要扫描整个keyspace,实时性较差,扫描时间与key数量正相关,如果key数量比较多,耗时可能会非常长。
- 信息不够丰富。首先记录的访问频率是一个与访问次数的对数成比例的相关近似值,不能够很直观的看出来热key的访问频率;另外,返回的信息中也没有key的类型和热key出现的时间等。
monitor命令统计
Redis提供monitor命令可以实时抓取出Redis服务器接收到的命令,可以对抓取的数据结合一些现成的分析工具(比如Redis-faina)统计出抓取时间段内的访问热key。
该方式存在以下几个问题:
- 该命令在高并发的条件下,有内存增暴增的隐患,还会降低Redis的性能,只能紧急情况下短暂使用,不能长时间使用。
- 该方式只能统计开启monitor命令的期间访问热key情况,对于过去已经发生的访问热key无法获取,无法应对一些瞬时的突发热key等情况。
Redis节点抓包分析
Redis客户端使用TCP协议与服务端进行交互,并且通信协议采用自定义的RESP协议,可以使用libpcap库对Redis-server监听端口抓包,然后按照RESP协议解析数据,并统计抓包期间内访问的热key。
该方式存在以下几个问题:
- 该方式实现相对比较复杂,有一定的开发成本。
- 同样只能统计开启抓包期间的访问热key情况,无法获取过去的热key。
- 开启期间对访问Redis-server性能有一定的损耗,而且ECS一般会部署多个Redis-server,全量开启会对系统负载有一定影响,因此无法长时间开启进行实时处理。
Client/Proxy端收集
可以对客户端工具进行封装,在发送请求前进行收集采集,同时定时把收集到的数据上报到统一的服务进行聚合计算。或者,如果业务通过Proxy访问缓存的话,可以在Proxy上进行收集,其他思路与Client端收集模式一致。
目前,比如,有赞自研分布式缓存系统zanKV、京东零售开源的热key探测框架(JD-hotkey)、得物热点探测框架(Burning)都是类似这种方案,在客户端进行收集,在聚合中心worker节点上进行热key统计,统计出来的热key可以推送到客户端进行本地缓存。
该方式存在以下几个问题:
- 在客户端收集的方案对客户端代码有一定的侵入,而且每种语言的SDK都需要进行开发,后期开发维护成本较高。
- 框架比较复杂,开发成本高。由于同一个key的访问可能同时出现在多个不同的客户端或者Proxy上,因此,在单个客户端或者Proxy上是无法统计热key的,因此,该方案需要一个聚合中心计算平台,收集不同Client/Proxy上访问的key,然后计算热key信息。
下图为京东开源的热key探测框架系统架构图:
三、基于Redis内核的热key统计
从上面的分析可以看到,目前存在的一些方案,要么无法高效快速的获取实时热key信息,要么架构比较复杂或者对业务有一定的侵入,得物自建Redis设计并研发基于Redis内核的热key统计方案,可以高效的统计并记录Redis实时热key信息,同时提供热key产生与热key失效的订阅通知。
实现原理简介
基于内核的Redis热key统计方案在Redis-server端实现,包含热key统计模块和热key通知模块两部分,另外提供热key日志记录查询与重置命令。
热key统计模块基于LRU队列实现统计key每秒内访问次数,当访问次数达到设置的热key阈值时,被判定为热key,热key加入热key队列用于提供实时查询。
基于内核的Redis热key统计方案提供热key订阅与主动通知功能,提供读热key、写热key、热key失效三个订阅通道channel,可用于Client/Proxy订阅热key消息,当key被判定为热key时,Redis-server主动向对应的消息通道广播热key消息。
实现原理图如下所示:
实现流程图
热key统计
为了能够高效进行热key统计,并且不消耗过多内存资源,在Redis中使用一个固定大小的LRU队列(大小可配置)来进行热key统计,记录数据结构采用了非常紧凑的格式设计,每个key的统计操作都是O(1)时间复杂度,保证高效统计的同时,统计工作消耗的内存资源不会随着Redis中存储的key数量增长而增长。
LRU队列中用于统计key访问记录的数据结构如下:
#define HOTKEY_NOTIFIED_BIT 1 #define ACCESS_COUNT_BITS 16 #define ACCESS_TIME_BITS 46 typedef struct hotkeyRecord { uint64_t notified:HOTKEY_NOTIFIED_BIT; // 热key是否通知或记录日志 uint64_t same_period:HOTKEY_NOTIFIED_BIT; // 每秒一个统计周期,同一个key每秒最多发送一次热key通知 uint64_t count:ACCESS_COUNT_BITS; // 热key计数 uint64_t access_time:ACCESS_TIME_BITS; // 热key计数记录起始时间,单位:毫秒 } hotkeyRecord;
热key统计默认以每秒一个周期,统计每个key在每秒时间内的访问次数,当每秒访问次数达到一定的阈值(阈值大小可配置)时,认定为是热key;同时,同一个时间周期内(即同一秒内)同一个key只记录一次热key,连续多次的不同时间周期内,同一个key连续出现热key现象会多次记录,同时,记录热key出现的时间与访问次数。
热key统计区分读热key与写热key,方便业务进行缓存或者其他相关处理。
被判定为热key的记录,会加入热key队列记录日志,可供查询,管控平台通过查询热key日志队列可以展示Redis-server节点实时热key信息;热key日志记录包括热key出现的时间、访问次数、key类型、读操作还是写操作等信息。
热key日志队列记录数据结构如下所示:
#define HOTKEY_NOTIFIED_BIT 1 #define ACCESS_COUNT_BITS 16 #define LOG_TIME_BITS 46 typedef struct hotkeyLogEntry { uint64_t notified:HOTKEY_NOTIFIED_BIT; uint64_t access_count:ACCESS_COUNT_BITS; // 热key计数 uint64_t access_time:LOG_TIME_BITS; // 热key计数记录起始时间,单位:毫秒 unsigned type; void *key; } hotkeyLogEntry;
热key通知
基于内核的Redis热key统计方案支持订阅模块与热key主动通知功能。
Redis-server提供读热key、写热key、热key失效三个订阅通道channel,可用于Client或者Proxy订阅热key相关消息;当出现读写热key时,Redis-server主动向对应的订阅通道广播热key消息;当一个热key出现写操作时,会向热key失效订阅通道广播key失效消息。
热key类型定义数据结构如下所示:
/* hotkey type */ #define READ_HOTKEY_NOTIFY 0 #define READ_HOTKEY_INVALID 1 #define WRITE_HOTKEY_NOTIFY 2
热key记录查询与重置命令
除了通过订阅通道主动通知外,Redis-server提供热key日志记录查询与重置命令,可供平台查询进行展示或者操作。
读命令热key查询与重置
可以查询指定长度的日志、或者从指定位置查询指定长度的日志:
// 查询读热 key 日志长度 readHotkeyLog len // 重置清空读热 key 日志 readHotkeyLog reset // 查询读热 key 日志 readHotkeyLog get // 查询默认长度,从日志队列头部开始查询数据 readHotkeyLog get [len] // 查询指定长度,从日志队列头部开始查询数据 readHotkeyLog get [index] [len] // 从指定 index 开始查询指定长度
写命令热key查询与重置
可以查询指定长度的日志、或者从指定位置查询指定长度的日志:
// 查询写热 key 日志长度 writeHotkeyLog len // 重置清空写热 key 日志 writeHotkeyLog reset // 查询写热 key 日志 writeHotkeyLog get // 查询默认长度,从日志队列头部开始查询数据 writeHotkeyLog get [len] // 查询指定长度,从日志队列头部开始查询数据 writeHotkeyLog get [index] [len] // 从指定 index 开始查询指定长度
四、总结
Redis热key是在Redis使用过程中一个比较常见的现象,同时,热key的实时探测与解决一直是业界的一个难点问题。得物自建Redis结合当前各种热key探测方案的优缺点,实现基于Redis内核的高性能实时热key统计方案。该方案具备如下优点:
- 实时性强:可实时统计热key信息,统计粒度为每秒
- 热key信息详细:热key信息包含热key出现的时间、访问次数、key类型、读操作或写操作等信息
- 支持订阅与查询:支持读热key、写热key、热key失效三种类型通知,可查询热key日志记录
往期回顾
1.盘点这些年搭建器在用户体验优化的实践|得物技术
2.解析Go切片:为何按值传递时会发生改变?|得物技术
3.基于IM场景下的Wasm初探:提升Web应用性能|得物技术
4.Java性能测试利器:JMH入门与实践|得物技术
5.彩虹桥架构演进之路-负载均衡篇|得物技术
文 / Miro
关注得物技术,每周一、三更新技术干货
要是觉得文章对你有帮助的话,欢迎评论转发点赞~
未经得物技术许可严禁转载,否则依法追究法律责任。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Mozilla 推出采用 .tar.xz 打包、更轻便的 Linux 版 Firefox 下载
Mozilla 宣布为 Linux 上的 Firefox 用户推出了一项改进,即增强了性能和与各种 Linux 发行版的兼容性。 开发团队正在将 Linux 版 Firefox 的打包格式从 .tar.bz2 转换为 .tar.xz,旨在利用更高效的 LZMA 压缩算法,以达到减小下载大小并缩短解压时间的目的。 下载量更小:Firefox .tar.xz 软件包平均比 .tar.bz2 软件包小 25%。 安装速度更快:通过改进的解压速度,在 Linux 上安装 Firefox 将比以往更快。.tar.xz格式的解压速度是.tar.bz2的两倍多。 增强兼容性:现代 Linux 发行版支持.tar.xz格式。此转换使 Firefox 与 Linux 社区的标准保持一致,从而确保更好的集成和兼容性。 当前用户无需采取任何措施:如果你的计算机上已安装 Firefox,则无需采取任何措施。Firefox 将继续照常运行和更新。 Mozilla解释称,之所以没选择解压速度更快一点的Zstandard,是因为他们看中了.tar.xz 更好的压缩效果,可以减少下载大小并节省带宽。此外,还有 .ta...
- 下一篇
开源日报 | Chrome牵头成立浏览器选择联盟;美图秀秀推出AI长头发功能;马斯克要开发游戏了;谷歌站上20000亿美金;Rust 1.83.0发布
欢迎阅读 OSCHINA 编辑部出品的开源日报,每天更新一期。 # 2024.11.29 今日要闻 Chrome 牵头成立「浏览器选择联盟」,目标是“反 Microsoft Edge” 近日,Chrome 联合 Opera、Vivaldi、Waterfox、Wavebox 等知名网络浏览器平台成立「浏览器选择联盟」(The Browser Choice Alliance),以对抗 Microsoft Edge 浏览器在 Windows 平台的垄断。 该联盟的理念是「用户拥有 Windows 平台的浏览器选择权」(consumers should have the right to use their browser of choice on Windows devices)。 在该联盟的网站中列举了 Edge 浏览器的诸多不正当竞争手段,如下载第三方浏览器时弹出安全提醒,更改默认浏览器时设置障碍,甚至在用户搜索其它浏览器时弹出「更改默认浏览器为 Edge」的提示等。 开源压缩软件 7-Zip 被曝严重安全漏洞 近日,知名压缩工具 7-Zip 被曝出了严重的安全漏洞,该漏洞编号为 CVE...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Red5直播服务器,属于Java语言的直播服务器
- CentOS7,8上快速安装Gitea,搭建Git服务器
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- CentOS8编译安装MySQL8.0.19