BigKey 的发现与处理

BigKey 可能会对 Redis 服务性能和稳定性产生显著影响,并可能导致服务下降或中断。本文介绍了 BigKey 的概念、检测方法以及在生产环境中处理 BigKey 的最佳实践。

目录

什么是 BigKey

在 Redis 中,BigKey 并不是指键本身很大,而是指与该键关联的值的大小。BigKey 通常根据两个标准进行评估:内存消耗和元素数量。常见的阈值包含:

  • 字符串:大小超过 5MB
  • 列表:元素数量超过 20,000
  • 集合:元素数量超过 10,000
  • 有序集合:元素数量超过 10,000
  • 哈希表:字段数量超过 10,000

注意:这些阈值作为指导提供,可能需要根据您的特定环境和需求进行调整。

BigKey 的影响

BigKey 可能以多种方式对 Redis 服务的性能和稳定性产生不利影响:

  • 线程阻塞:Redis 使用单线程模型处理数据。对 BigKey 的操作可能耗时较长,导致阻塞其他命令的执行,降低整体服务性能。
  • 客户端超时:由于单线程架构,对 BigKey 的操作可能导致 Redis 对客户端请求无响应,导致连接超时。
  • 网络带宽饱和:传输 BigKey 消耗大量网络带宽。例如,访问一个 1MB 的键每秒 1,000 次将产生 1GB/s 的网络流量,可能压垮标准网络基础设施。

在集群部署中,还会出现额外的关注点:

  • 内存不平衡:BigKey 可能导致单个节点的内存消耗不成比例,从而导致跨集群的资源利用率不理想。
  • 迁移瓶颈:在扩展操作期间,迁移 BigKey 可能会长时间阻塞 Redis,扰乱正常操作,甚至可能危及集群稳定性。

BigKey 的检测

使用巡检工具进行检测

灵雀云应用服务提供了 巡检 功能,可以帮助您检测 Redis 实例中的 BigKey。

  1. 编辑巡检工具部署配置以启用 BigKey 检测。

在实例所在的集群上,编辑 RdsInstaller 功能以启用 BigKey 检测。

# 首先检查 RdsInstaller 配置
$ kubectl -n rds-system get RdsInstaller rds -o yaml

输出如下:

apiVersion: middleware.alauda.io/v1
kind: RdsInstaller
metadata:
  name: rds
spec:
  ......
  inspection:
    concurrency: "10"
    dependency: true
    env:
    - name: ENABLE_REDIS_KEYS_INDICATOR
    image: xxx
    imagePullPolicy: Always
    instanceReportLimit: "10"
    name: inspection-operator
    namespace: rds-system
    ......
  1. 修改 ENABLE_REDIS_KEYS_INDICATOR 环境变量的值并保存。
$ kubectl -n rds-system edit RdsInstaller rds

spec.inspection.env 中的 ENABLE_REDIS_KEYS_INDICATOR 的值更改为 1。修改后的实例如下:

apiVersion: middleware.alauda.io/v1
kind: RdsInstaller
metadata:
  name: rds
spec:
  ......
  inspection:
    concurrency: "10"
    dependency: true
    env:
    - name: ENABLE_REDIS_KEYS_INDICATOR
      value: "1"
    image: xxx
    imagePullPolicy: Always
    instanceReportLimit: "10"
    name: inspection-operator
    namespace: rds-system
    ......

保存后,巡检工具将重启。您可以使用以下命令检查重启进度:

$ kubectl -n rds-system get pods -l name.operator=inspection-operator

输出如下:

$ kubectl -n rds-system get pods -l name.operator=inspection-operator
NAME                                   READY   STATUS    RESTARTS   AGE
inspection-operator-545468bd54-9g65p   1/1     Running   0          8s

注意:上述修改不是永久生效的,配置将在平台升级时被覆盖。

  1. 执行巡检

Redis -> 详情信息 页面,点击 巡检 按钮以启动实例的巡检。

一旦巡检开始,按钮将显示 巡检中...,完成后巡检按钮将变为可点击状态。

由于启用了 BigKey 检测功能,巡检工具将 SCAN 所有缓存中的数据,因此该过程可能需要相当长的时间。

  1. 查看巡检结果

巡检完成后,您可以在 Redis -> 详情信息 页面中的巡检报告中点击 查询 按钮,以查看巡检结果。

BigKey 检测报告查看入口

如果实例中确实存在 BigKey,巡检结果将列出 BigKey Top5 项目,如下图所示:

BigKey 检测报告

使用限制

  • 巡检工具会对 Redis 数据进行全库扫描,可能会对 Redis 服务产生一定的压力,建议在业务低峰期使用。
  • 目前,巡检工具仅支持检测 stringlistzset 类型。

使用命令行检测

Redis 社区提供了使用 redis-cli 检测 BigKey 的功能。在检测时,它会遍历/采样 Redis 实例中的所有 Key,并返回 Key 的整体统计信息及每种数据类型中最大的 Key。目前,bigkeys 支持分析 stringlistsetzsethashstream 类型。执行命令如下:

$ redis-cli -h <host> -a <password> --bigkeys

使用限制

  • redis-cli 检测也会对 Redis 数据进行全库扫描,可能会对 Redis 服务产生一定的压力,建议在业务低峰期使用。

BigKey 的优化

需要根据具体的业务场景和数据特征选择合适的优化方案,通常可以从以下几个方面进行考虑:

存储数据结构的优化

对于成员数量较多的集合类型(如 listsetzsethash 等),应将其拆分为多个 Key,并确保每个 Key 的成员数量在合理范围内。在 Redis 集群架构中,拆分大 Key 可以显著提高数据分片之间的内存平衡。

对数据进行压缩

若存储了大量的 JSON 或 HTML 缓存,可以考虑对这些数据进行压缩。此外,可以使用 ProtoBuffer 或 MessagePack 等序列化协议来减少数据大小。

定期清理过期数据

对于具有明确过期时间的数据,您可以通过设置过期时间自动清理过期数据。对于过期时间不确定的数据,应定期对其进行清理。尤其适用于 listsetzsethash 等数据结构,它们可能积累大量过期数据,因此建议结合使用 SCANDEL 来清除无效成员。

无论选择哪种优化方案,在清理现有的 BigKey 时,特别需谨慎使用 DEL 命令,因为 DEL 命令会阻塞 Redis 服务。建议使用 UNLINK 命令,该命令将异步删除 Keys,不会阻塞 Redis 服务。