BigKey 的发现与处理

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

目录

什么是 BigKey

Redis 中的 BigKey 并非指键本身很大,而是指该键对应的值的大小。BigKey 通常根据两个维度评估:内存占用和元素数量。常见阈值包括:

  • String:大小超过 5MB
  • List:元素数量超过 20,000
  • Set:元素数量超过 10,000
  • Sorted Set:元素数量超过 10,000
  • Hash:字段数量超过 10,000

注意:以上阈值仅作为参考,具体可根据您的环境和需求进行调整。

BigKey 的影响

BigKey 会从多个方面影响 Redis 服务的性能和稳定性:

  • 线程阻塞:Redis 采用单线程模型处理数据,BigKey 操作耗时较长,会阻塞其他命令的执行,导致整体服务性能下降。
  • 客户端超时:由于单线程架构,BigKey 操作可能导致 Redis 无法及时响应客户端请求,进而引发连接超时。
  • 网络带宽饱和:传输 BigKey 会消耗大量网络带宽。例如,1MB 大小的 Key 每秒访问 1000 次,将产生 1GB/s 的网络流量,可能超出普通网络设备承载能力。

在集群部署中,还存在额外问题:

  • 内存不均衡:BigKey 可能导致单个节点内存占用过高,造成集群资源利用不均衡。
  • 迁移瓶颈:扩缩容时迁移 BigKey 会长时间阻塞 Redis,影响正常业务,甚至威胁集群稳定性。

BigKey 的检测

使用检测工具进行检测

Alauda Application Services 提供了 Inspections 功能,帮助您检测 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
        ......
  2. 修改 ENABLE_REDIS_KEYS_INDICATOR 环境变量的值并保存。

    $ kubectl -n rds-system edit RdsInstaller rds

    spec.inspection.envENABLE_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
        ......

    保存后,inspection Operator 工具会重启。您可以通过以下命令查看重启进度:

    $ 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

    注意:上述修改非永久生效,平台升级时配置会被覆盖。

  3. 执行检测

    Redis -> Details Info 页面,点击 Inspection 按钮启动实例检测。

    检测开始后,按钮显示为 Inspecting...,检测完成后按钮恢复可点击状态。

    由于启用了 BigKey 检测功能,检测工具会对缓存中的所有数据执行 SCAN 操作,检测过程可能耗时较长。

  4. 查看检测结果

    检测完成后,可在 Redis -> Detail Info 的检测报告中点击 Query 按钮查看检测结果。

    BigKey 检测报告查看入口

    如果实例中存在 BigKey,检测结果会列出 BigKey Top5,示例如下:

    BigKey 检测报告

使用限制

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

使用命令行检测

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

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

使用限制

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

BigKey 的优化

需根据具体业务场景和数据特性选择合适的优化方案,通常关注以下几个方面:

存储数据结构优化

对于包含大量数据成员的集合类型(如 listsetzsethash 等),将其拆分为多个 Keys,确保每个 Key 的成员数量处于合理范围。在 Redis 集群架构中,拆分大 Key 能显著提升数据分片间的内存均衡性。

数据压缩

若缓存大量 JSON 或 HTML 数据,可考虑对数据进行压缩。此外,也可使用 ProtoBuffer、MessagePack 等序列化协议以减少数据体积。

定期清理过期数据

对于有明确过期时间的数据,可通过设置过期时间自动清理。对于过期时间不确定的数据,可定期清理。特别是 listsetzsethash 等数据结构,可能积累大量过期数据,建议结合 SCANDEL 命令清理无效成员。

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