bigywater.tech
Redis · 110

Redis hz 与 dynamic-hz

hz 是很少有人认真调的参数,但它是 Redis 后台任务的节拍:过期扫描、客户端超时、统计更新都靠它。这篇量它的两面:hz 小了,过期事件会晚多少;hz 大了,空闲时多耗多少 CPU;以及 dynamic-hz 什么时候会自动把它调高。

702 → 6.0 ms
hz 1 → 10 时,过期事件比 TTL 晚的中位数
1.3 → 7.1 ms/秒
空闲实例的 CPU:hz 10 → hz 500
4000 连接
dynamic-hz 把实际 hz 从 10 提到 20 所需的连接数(本次测量)

默认值

实测 · 本机执行输出
> CONFIG GET hz
1) "hz"
2) "10"
> CONFIG GET dynamic-hz
1) "dynamic-hz"
2) "yes"
  INFO server: hz = 10  configured_hz = 10

hz 默认 10,dynamic-hz 默认 yes。INFO server 里的 hz 是当前实际值,configured_hz 是配置值。

hz 与过期事件的及时性

每种 hz 20 次,空闲实例
实测 · 本机执行输出
   hz       事件延迟 中位 ms     最大 ms
    1            702.1    1704.2
   10              6.0       6.5
  100              7.5      21.1

hz 1 时后台扫描每秒一次,expired 事件比 TTL 晚的中位数 702 ms、最大 1704 ms(约一个扫描周期);hz 10 时中位数 6.0 ms;hz 100 时 7.5 ms,没有比 hz 10 更好。注意:这是空闲实例、少量 key 的情形;第 51 篇里量到,当库里有大量长 TTL 的 key 时,过期回收的及时性主要取决于抽样,而不是 hz 本身(那时没有测 hz 调大是否有帮助)。

hz 的代价

每个 hz 一个新实例,10 秒内 INFO 里 CPU 累计的增量
实测 · 本机执行输出
   hz    10 秒内 CPU 秒      折合每秒 ms
   10          0.013         1.27
  100          0.032         3.15
  500          0.071         7.07

空闲实例 10 秒消耗的 CPU:hz 10 是 0.013 s,hz 100 是 0.032 s,hz 500 是 0.071 s,大致随 hz 线性增长。绝对值很小(hz 500 也只是每秒约 7 ms),这是空闲实例、本机的数字;数据量大时每次 cron 的工作量也会变。

dynamic-hz

实测 · 本机执行输出
    已连接客户端    hz  configured_hz
         1    10             10
       100    10             10
       500    10             10
      2000    10             10
      4000    20             10

开着 dynamic-hz 时,连接数很多会自动提高实际 hz(configured_hz 不变)。本次测量里 500、2000 个连接时实际 hz 都还是 10,4000 个连接时才变成 20。触发的具体规则我没有去查源码,只记录了这几个点,中间没有二分。

分步演示:hz 的两面

Redis hz 与 dynamic-hz
本步的数据

    本文用到的工具与边界

    • 本机 macOS 27 / Redis 8.10.2 独立实例(本机回环端口,save 关闭),redis-cli 风格输出由自写的 RESP 客户端打印;计时用 time.perf_counter,数字每次运行会有小幅抖动。过期事件延迟用 keyspace notification 的 expired 事件计时;CPU 取自 INFO cpu 的 used_cpu_sys + used_cpu_user;客户端连接用空闲的原始 socket
    • 没有验证:数据量大时的 hz 影响、hz 高于 100 时的过期效果、dynamic-hz 的具体阈值、客户端超时检查(timeout 配置)的精度与 hz 的关系
    京ICP备2026067502号-1京公网安备11010502063487号