验证纯数字字符串的int编码在INCR后保持不变、在APPEND后立刻降级,以及超出64位整数范围的数字压根不会被当成int的规则。
String类型有三种编码:int、embstr、raw,纯数字字符串默认走int这条路。
操作SET counter 100 OBJECT ENCODING counter INCR counter OBJECT ENCODING counter APPEND counter2 "x" -- 对另一个int编码的key做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。
一个23位的超大数字,SET进去会是什么编码。
结果SET bignum 12345678901234567890123 OBJECT ENCODING bignum → :embstr(不是int!)
int编码要求这个数字必须能装进一个64位的有符号整数(大约±922亿亿的范围),12345678901234567890123 这个23位数字远远超出了这个范围,Redis一开始就没把它当整数处理,而是当成一个23字节的普通字符串——因为23字节小于44字节的阈值,按embstr编码存储。
每一步都是本文上面用redis-cli跑出来的原始结果。
OBJECT ENCODING / INCR / APPEND:验证int/embstr/raw三种编码的转换规则