作者总结分享 Redis Hotkey 定位和解决方法的优缺点。

作者:贲绍华,爱可生研发中心工程师,负责项目的需求与维护工作。其他身份:柯基铲屎官。

爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。

本文约 800 字,预计阅读需要 2 分钟。

什么是 Hotkey,会有什么问题?

1.1 什么是 Hotkey?

顾名思义即 Redis 实例中的热点数据,当客户端频繁访地查询、读取、写入同一个 key 时,它被称之为 Hotkey。

1.2 会有什么问题?

1.2.1 网络问题

单机的资源是有限的,Hotkey 无法充分利用集群分担流量时,会导致各实例间资源无法充分合理应用。

Hotkey 所属实例的网卡也会持续高负载的状态,可能会出现相应延迟的问题。

1.2.2 缓存穿透

当 Hotkey 失效或所在节点实例状态异常时,流量请求会直接打到数据库上。

1.2.3 主从同步延迟

在 Redis 中,主从同步是异步进行操作的,但如果单节点 Hotkey 持续占用过高的带宽资源,则可能会造成主从延迟或中断。

如何发现 Hotkey?

2.1 客户端统计

这里的客户端可以是具体的业务端,也可以是 proxy 层,根据 key 的调用情况进行统计与分析。

优点

  • 实现成本相对较低。
  • 可以根据统计情况灵活调整客户端的统计指标与算法,灵活配置客户端缓存。

缺点

  • 对业务开发的侵入性:需要预先埋点,添加相关逻辑和代码。这涉及到对业务开发的改动和调整,可能增加开发复杂性和维护成本。
  • 监测存在延迟:多个客户端统计时汇总分析比较繁琐,上报与分析的过程往往并不是实时的,存在一定的延迟。

    2.2 Monitor 监控

    Redis 提供了 Monitor 监控命令,使用 Monitor 命令可以实时监控 Redis 数据库的所有命令操作,包括对 Hotkey 的读取和写入操作,通过对返回的执行命令进行统计来分析 Hotkey 的分布。

方案推荐

Facebook 开源的 redis-faina(Python),提供了对 Monitor 的一些分析与定位。

优点

  • 可以清楚的知道 key 的操作行为(写入还是读取)。
  • 准确定位客户端来源。

缺点

  • Monitor 命令本身会影响 Redis 的性能,特别是在高负载环境中。它会占用部分 Redis 服务器的 CPU 资源和网络带宽,在 Redis 官方文档 中描述如下,运行单个 Monitor 客户端可能会使吞吐量减少50%以上:
In this particular case, running a single 
MONITOR client can reduce the throughput by more than 50%. Running more 
MONITOR clients will reduce throughput even more

2.3 Hotkeys

从 Redis 4.0.3 版本开始,Redis 引入了 hotkeys 的命令来帮助定位 Hotkey。该命令可用于识别在 Redis 数据库中访问频率最高的键。

对性能要求不是太高的业务场景下,建议使用该进行 Hotkey 的定位与分析。使用前需要先配置 Redis 的内存淘汰策略。

优点

  • 易用性:内置命令直接调用即可。
  • 实时性:该命令提供的信息是实时的,能够及时反映当前的热点键。

    缺点

  • 性能影响:由于它是一个全量的Hotkey数据,特别是存在大量hotkey的场景下会对性能产生较大影响,因此不推荐在生产环境频繁执行;
  • 局限性:该命令返回的结果是基于Redis自身内部的采样与统计算法,根据机器资源的或预期场景的不同,该结果可能并不是100%符合预期的;
  • 完整性:该命令只提供了热点键的基本信息,无法知道更详细的统计和分析信息,需要向业务侧确认;

2.4 TCP 抓包

使用这种方式可以做到对业务端无侵入性、对 Redis 实例本身性能无影响。

方案推荐

ELK 提供了一个名为 packetbeat 的抓包插件,可以对 Redis 的 TCP 报文进行抓包与分析。但往往需要搭配 ELK 一起使用,单独使用 packetbeat 插件的话也需要额外做一些定制化变更。

优点

  • 实时性:可以实时捕获 Redis 客户端与 Redis 服务器之间的网络通信,包括请求和响应数据,以获取最新的 Hotkey 信息。
  • 适用范围更广:适用于任何 Redis 实例,不论是单机还是分布式部署,无论是云上还是本地。只要网络流量可以访问,就可以使用 TCP 抓包进行分析。
  • 独立性:这种方式是独立于业务侧与 Redis 实例之外的,无需业务埋点、无需更改或配置 Redis,同时也避免对 Redis 实例所在的机器性能造成额外的负担。

    缺点

  • 复杂度过高:无论是基于自行实现还是 packetbeat,都需要进行一定的定制化调整,使用成本相对较高。
  • 稳定性:当网络环境不稳定时,该方式可能存在一定误差。
  • 隐私与安全:TCP 报文包含了完整都的请求和响应数据可能会涉及到敏感信息的泄露(如密码、敏感数据等)。

如何解决?

3.1 Redis cluster 数据分片

将数据按照一定的规则进行分片存储,使不同的键分散在不同的 Redis 实例或分片中。这样可以减少单个实例的负载,提高整体性能。

可以使用 Redis Cluster 来实现分片,或者结合应用程序的逻辑进行手动分片。但该方式可能并不适用单个或少量 key 为 Hotkey 的场景。

3.2 多级缓存

通过第二小节的方式定位到 Hotkey 后,可以对 Hotkey 灵活调整缓存策略,比如客户端本地+分布式缓存、全局缓存+局部缓存等。

3.3 监控优化

对Redis实例所在机器完善监控与告警,多维度分析 Hotkey 场景下机器的 QPS、内存、网络等资源的使用情况。

当达到策略阈值时,可以配合自动化运维增加一些如:扩容、调整缓存配置、slot迁移等策略。

3.4 根据业务拆分子 key

该方式适用于 key 的数量较少且可以对 key 或 value 自身进行拆分的情况,令 Hotkey 尽量分散的落到不同的实例上。

3.5 缓存策略与 TTL 优化

合理配置 TTL,并使用适当的缓存策略,如 LRU(Least Recently Used)或 LFU(Least Frequently Used),以便自动淘汰冷数据并保留热点数据。

避免 Hotkey 过期导致频繁的缓存击穿的情况。

分类: 技术分享