Hotkey Collector 内部结构如下所示 , 包含 LFU Counter、Syncer 和 Etrace Client 三部分:
文章插图
Etrace 是一个内部的应用监控平台 , 类似的开源产品是 CAT [3]基本的工作流程是 , LFU Counter 负责记录 key 的访问频次 , Syncer 会定期将统计数据通过 Etrace Client 发送给远端的服务器 。另外 , 为了避免向服务端发送过多无效的数据 , 内部会预先设置一个阈值 , 超过阈值的才发送到服务端 。
按照预先的设计 , 我们将会有一个实时计算的服务去拉取 Etrace 上的数据 , 进行聚合计算得到当前的热点 key 。但不幸地是代理中间件改造上线后的很长一段时间内 , 这个实时计算服务的开发都未被提上日程 , 分析下来主要是 ROI 低和维护成本高 , 因此在业务上如果要查热 key 就只能在 Etrace 上手动戳 event 碰运气比如:
文章插图
由于使用起来很麻烦 , 用户在第一次体验之后基本就放弃了 , 不会再用第二次 , 甚至连我们自己都不愿意使用… 在当时我们急需要找到一种更好的方案去解决用户体验和系统复杂度的问题 , 让该特性能真正地赋能于业务 。
最终的方案
对前面方案进行优化的话 , 可以从以下两个方面入手:
- 如何在不增加实时计算组件提升成本的前提下高效地聚合数据?
- 如何提升用户体验 , 让用户方便地使用?
针对第一点 , 当时第一个想法是能不能把聚合逻辑放在代理进程内 , 这样的话就不用再依赖任何外部组件 , 可以降低整个系统的复杂度和维护成本 。但这里会有个问题 , 之前设计外部聚合组件的初衷是为了聚合不同机器的数据 , 现在采用单机数据会不会有问题 , 逻辑是不是站得住脚?
仔细思考下来 , 逻辑上是成立的 , 因为到达业务的流量是负载均衡过的 , 不同实例上的流量是比较均匀的 , 差不太多的 , 基于这个局部可以代表整体的原则 , 那么单实例上的热 key 就可以代表全局的一个情况 。
【如何快速定位 Redis 热 key?】另外 , 就易用性和使用体验上来说 , 如果聚合的数据在进程内 , 我们可以提供 HOTKEY 类似的自定义命令 , 让用户通过 redis-cli 直接获取 。
最终的方案如下 , 已略去无关细节:
文章插图
实现上来说 , 每个集群会有一个全局的 Hotkey Collector , 每个 client 上有自己独立的 Counter , Counter 依旧采用前面提到的 LFU[4] 算法 , Collector 会定时地去收集每个 Counter 的数据并进行聚合 , 聚合的时候不会使用真实的计数 , 而是使用概率计数[5] , 并且为了适应访问模式的变化 counter 的值会随着时间衰减 , 整体上与 redis lfu[6]非常类似 。
下面是一个生产环境的真实例子 , 展示了近一段时间内比较热的 key:
文章插图
注:
- 默认使用的 log factor 因子是 10 , counter 值每分钟衰减一半
- Collector 默认的容量是 32 , 只记录请求频次最高的 32 个 key
- 输出的结果与 redis-cli --hotkeys 非常类似 , counter 具体含义可以参考 Using Redis as an LRU cache[7] 一文末尾表格
当前的方案虽然能够快速定位系统中的热 key , 但并没有真正解决热 key 本身带来的问题 , 仍旧需要业务方自行改造或者将那些热点 key 调度到单独的节点上 , 成本是比较高的 , 甚至有的业务还会自己做 local cache 。
本着更好地服务于客户的原则 , 我们后面将会考虑在代理内实现热点 key 的缓存 , 不过在代理内实现缓存的话需要先解决内存占用、数据一致性和性能的问题 , 这块暂时还没有非常好的方案 , 仍旧在调研之中 , 好的消息是 Redis 6 计划实现 server-assisted client side caching[8] , 如果有可能的话我们会第一时间考虑对接 。
推荐阅读
- 荷叶茶如何制作方法,茉莉花茶如何喝
- 菊花茶如何泡,孕妇喝菊花茶好不好
- 金银花茶十大名牌简述,金银花茶如何贮存
- 花草茶的成分及功能,如何挑选和保持花草茶的秘诀
- 从后端到前端的转变:如何选择框架?
- Java 如何利用钩子函数实现优雅停服?刨根问底
- 花草茶主要品种有哪些,如何保存花草茶
- 花茶怎样挑选,花茶如何品饮
- 痔疮肿痛如何快速消减的方法
- 淘数据是什么东西 淘数据如何使用