bigywater.tech
Redis · 13

String 编码转换

验证纯数字字符串的int编码在INCR后保持不变、在APPEND后立刻降级,以及超出64位整数范围的数字压根不会被当成int的规则。

INCR不降级
在int编码框架内完成运算
APPEND必降级
强制转raw,与结果长度无关
64位范围外→embstr
超大数字从一开始就不算int

做的事:给纯数字字符串做各种操作,看编码怎么变

String类型有三种编码:int、embstr、raw,纯数字字符串默认走int这条路。

操作SET counter 100 OBJECT ENCODING counter INCR counter OBJECT ENCODING counter APPEND counter2 "x" -- 对另一个int编码的key做APPEND

验证:INCR不会破坏int编码,APPEND会

两种看起来都是"修改",结果完全不同。

结果SET counter 100 OBJECT ENCODING counter → :int INCR counter → 101 OBJECT ENCODING counter → :int(还是int!) SET counter2 100 APPEND counter2 "x" GET counter2 → "100x" OBJECT ENCODING counter2 → :raw(不再是int)

原因是:INCR 是拿出int编码里存的那个真正的C语言整数,做加法,再存回去——全程都在int编码的框架内运作,运算完之后还是一个合法的整数,编码自然保持int。APPEND 则是在做字符串拼接,"100"变成"100x"之后根本不再是一个合法的整数,int编码存不下这种东西,只能转成能存任意字节的raw。

验证:数字大到超出范围,压根就进不了int编码

一个23位的超大数字,SET进去会是什么编码。

结果SET bignum 12345678901234567890123 OBJECT ENCODING bignum → :embstr(不是int!)

int编码要求这个数字必须能装进一个64位的有符号整数(大约±922亿亿的范围),12345678901234567890123 这个23位数字远远超出了这个范围,Redis一开始就没把它当整数处理,而是当成一个23字节的普通字符串——因为23字节小于44字节的阈值,按embstr编码存储。

三种编码的判断顺序是:先看这个字符串是不是一个能装进64位整数的纯数字——是就用int;不是的话再看长度是否≤44字节——是就用embstr;否则用raw。而且这个判断只在写入/SET的时候发生一次,后续像APPEND这种会改变内容本质的操作,会强制降级到更"兜底"的编码(int/embstr → raw),但不会有相反方向的自动升级。

分步演示:三种编码的判断规则和转换时机

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

INCR保持int,APPEND降级,超大数字进不了int
这一步新验证的操作

    本文用到的工具

    • 本机 Redis 8.10.1 单节点
    • OBJECT ENCODING / INCR / APPEND:验证int/embstr/raw三种编码的转换规则
    京ICP备2026067502号-1京公网安备11010502063487号