bigywater.tech
Redis · 18

OBJECT ENCODING 观察编码变化

验证编码转换检查到底发生在哪个动作上:把配置阈值调低后,已有数据不会被追溯转换,只有的写操作才会立刻触发按新阈值重新评估。

不追溯
调低阈值不会影响已存在的旧数据
读不触发
HGET不会重新评估编码
写立刻触发
HSET按最新阈值立刻转换

做的事:先建一个listpack编码的hash,再动态调低阈值

前面几篇文章验证的都是"写入时"的编码判断,这次验证判断到底发生在哪个动作上。

操作CONFIG SET hash-max-listpack-entries 512 HSET 20个字段到h1 OBJECT ENCODING h1 CONFIG SET hash-max-listpack-entries 5 -- 把阈值调到远低于h1现有的20个字段 OBJECT ENCODING h1 -- h1完全没有被碰过

验证:调低配置,不会追溯性地转换已有的key

h1已经有20个字段,远超过新设的阈值5,但没人碰它。

结果调低阈值之前: OBJECT ENCODING h1 → listpack (20个字段,阈值512) CONFIG SET hash-max-listpack-entries 5 (阈值改小了,h1完全没有被读写) OBJECT ENCODING h1 → :依然是listpack!

哪怕新的阈值(5)远小于h1已有的字段数(20),只要没有的读写操作发生在h1上,它的编码就不会被重新评估——CONFIG SET改的只是"以后写入时用什么标准判断",不会主动扫描现有数据、逐个检查是否需要转换。

验证:一次读不触发,一次写立刻触发

分别做一次HGET(读)和一次HSET(写),看哪个会触发重新评估。

结果HGET h1 f1 (读取,不修改任何东西) OBJECT ENCODING h1 → :依然是listpack(读不触发) HSET h1 f21 v21 (写入一个新字段) OBJECT ENCODING h1 → :hashtable(写立刻触发!)

验证了编码检查的确切时机:只有执行了写操作(这里是新增一个字段),Redis才会按当前的配置阈值重新判断这个对象该用什么编码——这一次判断发现21个字段已经超过阈值5,于是立刻转换成hashtable。单纯的读操作,哪怕读的是同一个key,也不会触发这次重新评估。

这是一个很实用的运维知识点:线上调整像 hash-max-listpack-entries 这类编码阈值参数,不会立即影响已经存在的旧数据——已有的key会一直用旧编码,直到有一次写操作命中它,才会按新阈值重新判断。如果想让配置变更对存量数据生效,得靠后续业务的自然写入,或者手动触发一次读改写(比如给自己加个无意义的写操作)。

分步演示:编码重新评估发生在哪个动作上

每一步都是本文上面用redis-cli跑出来的原始结果。

配置变更不追溯,读不触发,只有写才触发重新评估
这一步新验证的动作

    本文用到的工具

    • 本机 Redis 8.10.1 单节点
    • CONFIG SET hash-max-listpack-entries / OBJECT ENCODING:验证配置变更、读、写三种动作对编码的影响
    京ICP备2026067502号-1京公网安备11010502063487号