Redis Object
Based on Redis 7.0.11.
Redis 对外支持的数据类型(String、List、Hash、Set、ZSet)并不是直接使用其定义的数据结构,而是基于另外的一套对象系统。对象系统除了可以根据不同场景选择不同底层数据结构外,还实现了基于引用计数的对象共享和垃圾回收以及缓存淘汰机制。
Redis Object 定义
1 | typedef struct redisObject { |
type:记录对象类型类型 取值 OBJ_STRING 0 OBJ_LIST 1 OBJ_SET 2 OBJ_ZSET 3 OBJ_HASH 4 encoding:记录对象的编码及底层实现编码 取值 对应数据结构 OBJ_ENCODING_RAW 0 SDS OBJ_ENCODING_INT 1 long OBJ_ENCODING_HT 2 字典 OBJ_ENCODING_INTSET 6 整数集合 OBJ_ENCODING_SKIPLIST 7 跳表和字典 OBJ_ENCODING_EMBSTR 8 embedded 编码的 SDS OBJ_ENCODING_QUICKLIST 9 OBJ_ENCODING_STREAM 10 OBJ_ENCODING_LISTPACK 11 lru:缓存淘汰策略相关refcount:引用计数ptr:底层数据指针
该结构采用了 Bit Field 来降低内存的占用。Redis 会根据实际情况(数据类型,数据大小)选择相对合适的 encoding 来提高性能与效率。
| type | encoding | 对象 |
|---|---|---|
| OBJ_STRING | OBJ_ENCODING_RAW | ptr 指向 SDS |
| OBJ_STRING | OBJ_ENCODING_INT | ptr 值就是整数值,而非地址 |
| OBJ_STRING | OBJ_ENCODING_EMBSTR | 字符串较短时,一次分配一块内存连续存放 redisObject 和 sdshdr 对象 |
| OBJ_LIST | OBJ_ENCODING_QUICKLIST | ptr 指向 quicklist |
| OBJ_SET | OBJ_ENCODING_HT | ptr 指向 dict,只使用 key,值设为 NULL |
| OBJ_SET | OBJ_ENCODING_INTSET | ptr 指向 intset,所有元素都是整数,且数量不超过 512 |
| OBJ_ZSET | OBJ_ENCODING_LISTPACK | ptr 指向 listpack,元素数量 < server.zset_max_listpack_entries 且元素大小 < server.zset_max_listpack_value |
| OBJ_ZSET | OBJ_ENCODING_SKIPLIST | ptr 指向 zset{dict, skiplist}, |
| OBJ_HASH | OBJ_ENCODING_LISTPACK | ptr 指向 listpack,元素数量 < server.zset_max_listpack_entries 且元素大小 < server.zset_max_listpack_value。暂时不支持 HT 转成 LISTPACK |
| OBJ_HASH | OBJ_ENCODING_HT | ptr 指向 dict |
对象引用计数
Redis 通过追踪 redisObject#refcount,在适当的时候自动释放 refcount == 0 的对象。
引用计数除了用作垃圾回收外,还可用作对象共享。不过对象共享需要查找到一个具有相同值的对象,O(N2) 复杂度,CPU 开销大。
Key takeaways
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 爱吃胡萝卜!

