背景

在 Redis 中,热 key 指的是那些在一段时间内访问频次比较高的键值,具体到业务上,商品的限时抢购、瞬时的新闻热点或某个全局性的资源,都极有可能产生热点 key。

热点 key 的出现可能会对系统的稳定性和可用性造成影响,比如对应节点的网卡带宽被打满,出现丢包重传,请求波动耗时大幅上升,甚至影响到业务的正常使用,引发用户的不满。因此,在日常的工作中,我们需要着重避免这种情况的出现,比如在设计和编码阶段避免引入全局性热 key,或者在设计时考虑热 key 出现时的应对方案。

可能的方案

热点 key 即使我们在设计和开发时已经极力避免,然而在真实的生产环境中还是可能依旧存在的,导致其继续出现的原因有以下几种:

  • 有一些边界 case 没有考虑
  • 异常或非预期的流量

既然不可能完全避免,我们就需要有一种方法能够在出问题的时候快速定位有没有热 key 以及热 key 具体是啥,来帮助业务快速排障,定位问题的根源。如果要设计定位方案的话,我们可以从 Redis 请求路径上的节点来着手,比如在客户端、中间层和服务端,具体来说如下:

客户端收集上报

改动 Redis SDK,记录每个请求,定时把收集到的数据上报,然后由一个统一的服务进行聚合计算。方案直观简单,但没法适应多语言架构,一方面多语言 SDK 对齐是个问题,另外一方面后期 SDK 的维护升级会面临比较大的困难,成本很高。

代理层收集上报

如果所有的 Redis 请求都经过代理的话,可以考虑改动 Proxy 代码进行收集,思路与客户端基本类似。该方案对使用方完全透明,能够解决客户端 SDK 的语言异构和版本升级问题,不过开发成本会比客户端高些。

Redis 数据定时扫描

Redis 在 4.0 版本之后添加了 hotkeys 查找特性,可以直接利用 redis-cli --hotkeys 获取当前 keyspace 的热点 key,实现上是通过 scan + object freq 完成的。该方案无需二次开发,能够直接利用现成的工具,但由于需要扫描整个 keyspace,实时性上比较差,另外扫描耗时与 key 的数量正相关,如果 key 的数量比较多,耗时可能会非常长。

Redis 节点抓包解析

在可能存在热 key 的节点上(流量倾斜判断),通过 tcpdump 抓取一段时间内的流量并上报,然后由一个外部的程序进行解析、聚合和计算。该方案无需侵入现有的 SDK 或者 Proxy 中间件,开发维护成本可控,但也存在缺点的,具体是热 key 节点的网络流量和系统负载已经比较高了,抓包可能会情况进一步恶化。

大厂的选择

所有的 Redis 请求都是经过透明代理 Samaritan 的,并且该代理是由我们自己开发维护的,在代理层改造的成本完全受控,因此我们选择了方案二,即在代理层进行收集上报。
大的方向确定之后,需要考虑具体的细节,比如:

  • 记录所有请求如何能够保证不占用过多的内存甚至 OOM ?
    既然我们只关心热 key,而不是要统计所有 key 的 counter,那么就可以用 LFU 只保留访问频次最高的,
  • 记录所有请求如何能够保证代理的性能, 请求耗时不会有明显的上升?
    需要结合代理具体的实现去考虑

代理内部的实现方案:

  • 每个 redis node 会创建一个与之对应的唯一的 client,其上的所有请求都采用 pipeline 执行
  • 每个 client 内部都有自己的 Hotkey Collector,不同 Collector 间相互独立

Hotkey Collector

  • 内部结构

Etrace 是一个内部的应用监控平台,类似CAT

工作流程

  • LFU Counter 负责记录 key 的访问频次
  • Syncer 会定期将统计数据通过 Etrace Client 发送给远端的服务器
    为避免向服务端发送过多无效数据,内部会预先设置一个阈值,超过阈值的才发送到服务端。

按设计,会有一个实时计算的服务去拉取 Etrace 上的数据,进行聚合计算得到当前的热点 key。但不幸地是代理中间件改造上线后的很长一段时间内,这个实时计算服务的开发都未被提上日程,分析下来主要是 ROI 低和维护成本高,因此在业务上如果要查热 key 就只能在 Etrace 上手动戳 event 碰运气。由于使用起来很麻烦,用户在第一次体验之后基本就放弃了,不会再用第二次,甚至连我们自己都不愿意使用… 在当时我们急需要找到一种更好的方案去解决用户体验和系统复杂度的问题,让该特性能真正地赋能于业务。

最终方案

对前面方案进行优化:

  • 如何在不增加实时计算组件提升成本的前提下高效地聚合数据?
  • 如何提升用户体验,让用户方便地使用?

第一点,第一个想法是能不能把聚合逻辑放在代理进程,这样就不用再依赖任何外部组件,可以降低整个系统的复杂度和维护成本。但有个问题,之前设计外部聚合组件的初衷是为了聚合不同机器的数据,现在采用单机数据会不会有问题?
仔细思考下来,逻辑上是成立的,因为到达业务的流量是负载均衡过的,不同实例上的流量是比较均匀的,差不太多的,基于这个局部可以代表整体的原则,那么单实例上的热 key 就可以代表全局的一个情况。
就易用性和使用体验上来说,如果聚合的数据在进程内,我们可以提供 HOTKEY 类似的自定义命令,让用户通过 redis-cli 直接获取。

最终方案如下:

每个集群会有一个全局 Hotkey Collector,每个 client 上有自己独立的 Counter,Counter 依旧采用LFU,Collector定时收集每个 Counter 的数据并聚合,聚合时不会使用真实的计数,而是使用概率计数,并且为了适应访问模式的变化 counter 的值会随着时间衰减,整体上与 redis LFU 非常类似。

下面是一个生产环境的真实例子,展示了近一段时间内比较热的 key:

默认使用的 log factor 因子是 10,counter 值每分钟衰减一半
Collector 默认的容量 32,只记录请求频次最高的 32 个 key

输出的结果与 redis-cli --hotkeys 非常类似。

如何快速定位 Redis 热 key相关推荐

  1. 如何快速定位 Redis 热 key?

    背景 在 Redis 中,热 key 指的是那些在一段时间内访问频次比较高的键值,具体到业务上,商品的限时抢购.瞬时的新闻热点或某个全局性的资源,都极有可能产生热点 key. 热点 key 的出现可能 ...

  2. Redis 热 Key 发现以及解决办法

    背景介绍 最近在技术交流微信群里看大家讨论技术,其中有谈到 Redis 热 Key 的一些问题解决方案,我也仔细思考了一下我们目前系统中 Redis 的使用场景,我们是不是也存在热 Key 问题,或者 ...

  3. 不区分语言开发工具1(服务压力测试,跨域问题解决,Redis进行密码的设置,设计模式,搭建FTP局域网服务,redis热key,redis哨兵,VueRouter模式)

    1. Apache的ab工具:(压测的具体使用,可以实现添加参数进行相关的测试) 压测的概念: 吞吐率(Requests per second) 概念:服务器并发处理能力的量化描述,单位是reqs/s ...

  4. 分布式环境下对部分热数据(如redis热key,热请求)进行探测,并对探测结果及时同步到各个client实例的JVM内存的方案简述

    可先阅读之前的这篇,有赞的热key探测及缓存方案. 常见场景 突发性的无法预先感知的热点数据请求,或者有阵发性明显热点数据的. 譬如突然大量请求都命中了redis的某个分片,造成该redis卡顿,影响 ...

  5. Redis热key和大key问题

    一.热key问题 热key问题: 在redis数据库中有些访问量特别大的数据,比如热门商品信息.热门话题等,大量的请求去访问redis上的某个特定key,会造成流量过于集中,达到物理网卡或者内存上限, ...

  6. redis热key卡槽节点分配算法

    redis哈希槽分配 详解地址:CSDN hot key卡槽节点均分算法 该算法主要是解决hot key在redis集群中单节点访问问题,使hot key均分到redis不同节点上,防止单节点压力过大 ...

  7. redis热key监控

    https://mp.weixin.qq.com/s/QoNx8yyfznu_W0cWDTob2Q

  8. 京东毫秒级热key探测框架设计与实践,已完美支撑618大促

    在拥有大量并发用户的系统中,热key一直以来都是一个不可避免的问题.或许是突然某些商品成了爆款,或许是海量用户突然涌入某个店铺,或许是秒杀时瞬间大量开启的爬虫用户, 这些突发的无法预先感知的热key都 ...

  9. Redis——热点key问题

    本篇主要介绍Redis中的热点Key问题,包括热点Key产生的原因.如何监控发现热点key以及热点Key的解决方案: 其实热key问题说来也很简单,就是瞬间有大量的请求去访问redis上某个固定的ke ...

最新文章

  1. 基于源码仿建视频解析网站
  2. cron表达式详解 Elastic-Job名次解释
  3. Central Europe Regional Contest 2012 Problem c: Chemist’s vows
  4. highgui java opencv_OpenCV在C Qt应用程序中的highgui
  5. MySQL闪回原理与实战
  6. linux ti 电池驱动_全球跨国车企电动汽车平台和电池系统对比
  7. 文件服务和对象存储服务器,对象存储与块存储服务
  8. Blocks in Objective-C
  9. EmEditor Professional v14/15/16/17/18 最新版 注册码 2000组(终身授权)
  10. 6 RFID的ISOIEC标准
  11. 在matlab中讲矩阵一次性检验,层次分析法原理和matlab代码实现
  12. [bzoj2434][AC自动机][树状数组]阿狸的打字机
  13. 等差数列_等比数列公式
  14. eclipse官网下载不了eclipse开发工具的解决方法
  15. 2022-2028年全球与中国近红外照相机行业发展趋势及投资战略分析
  16. 腾讯区块链的三年与它的打法
  17. 如何设置下拉框多选以及设置多选值
  18. 普通中继模型-吞吐量
  19. Python 之return 自定义返回值
  20. ENVI下植被指数模型详解

热门文章

  1. 《Kotlin 程序设计》第十二章 Kotlin的多线程:协程(Coroutines)
  2. 资深程序员雷总对代码的执念
  3. 安卓手机免root权限恢复微信聊天记录(以vivo手机为例)
  4. Linux内核学习笔记——Linux中的用户组和权限管理(UID是什么?)
  5. 基于html+css+javascript+jquery+bootstarp响应式网页设计——大理我的家乡旅游景点
  6. 第1130期AI100_机器学习日报(2017-10-22)
  7. 光伏发电到底能带我们走多远?
  8. 【呆瓜学maven】Maven介绍(创建工程项目以及下载所需要的jar包)
  9. vue打开新的标签页
  10. python训练好的图片验证_Python图片验证码降噪处理实例