验证一个纯整数set加非整数成员的转换路径,跟纯整数但数量超限的转换路径,看intset是怎么走向两种不同结局的。
intset是专门为"全是整数"的set设计的紧凑编码。
操作SADD myset 1 2 3 OBJECT ENCODING myset SADD myset "hello" -- 加入一个非整数成员 OBJECT ENCODING myset
结果确认了intset的"纯度"要求。
结果SADD myset 1 2 3 OBJECT ENCODING myset → :intset SADD myset "hello" OBJECT ENCODING myset → :listpack(不是intset了!)
intset要求集合里所有成员都必须是整数——只要混入一个字符串,哪怕集合本身还很小,Redis也会立刻把它转换成通用的 listpack 编码(能存任意类型),不会因为大部分还是整数就继续用intset硬撑。
如果一直全是整数,只是数量超过了阈值,会转成listpack还是别的?
结果(set-max-intset-entries设成128)SADD 128个纯整数 OBJECT ENCODING → :intset SADD 第129个纯整数 OBJECT ENCODING → :hashtable(不是listpack!)
这里走的是跟"混入非整数"完全不同的路径:数量超限但全是整数时,Redis直接跳过listpack,一步转成 hashtable。原因是:intset的设计目标就是"大量纯整数还能保持紧凑",一旦数量多到要放弃intset,说明这个集合本来就偏大,listpack这种同样是连续内存的紧凑结构在数据量大时不划算(插入/查找退化成线性扫描),所以直接一步到位用哈希表。
每一步都是本文上面用redis-cli跑出来的原始结果。
OBJECT ENCODING / CONFIG SET set-max-intset-entries:对比两种升级路径