Redis的encoding编码
Redis的底层设计中RedisObject存在encoding用于针对数据进行优化,而在不同的类型中也有不同的优化选择,这篇文章只对所有的编码类型进行描述,并不说明Redis数据类型分类选择优化编码规则进行描述
#define OBJ_ENCODING_RAW 0 /* Raw representation */
#define OBJ_ENCODING_INT 1 /* Encoded as integer */
#define OBJ_ENCODING_HT 2 /* Encoded as hash table */
#define OBJ_ENCODING_ZIPMAP 3 /* Encoded as zipmap */
#define OBJ_ENCODING_LINKEDLIST 4 /* No longer used: old list encoding. */
#define OBJ_ENCODING_ZIPLIST 5 /* Encoded as ziplist */
#define OBJ_ENCODING_INTSET 6 /* Encoded as intset */
#define OBJ_ENCODING_SKIPLIST 7 /* Encoded as skiplist */
#define OBJ_ENCODING_EMBSTR 8 /* Embedded sds string encoding */
#define OBJ_ENCODING_QUICKLIST 9 /* Encoded as linked list of ziplists */
#define OBJ_ENCODING_STREAM 10 /* Encoded as a radix tree of listpacks */
raw
即普通的SDS普通编码方式的编码类型,该编码类型为原始类型,可通用存储数据
int
数据会先设置为原始类型,然后判断长度是否大于20个字节(指针本身就占用了8个字节,尝试不进行创建内存,而直接使用指针地址)再进行尝试转换为整型值(20位大小的整型值就在8个字节以内),就可以使用指针来存储整型值,节省了内存空间与内存IO
ht(hashTable)
该类型在实际上的表现就是dict(字典),这是因为该结构主要服务为Redis的hash数据类型,而该类型实质是就上就类似一个嵌套的MAP
该编码在hash,set中使用,Set 数据结构底层实现为一个value 为 null 的 字典( dict )
zipmap
可以看成压缩字典,根据ziplist类似原理来实现
linkedlist
常见的双端链表结构,数据存储在节点上,是老的list类型的实现,被quicklist替换
淘汰猜测:数据存储在上造成需要持续IO+链表内存地址分散
ziplist
采用紧凑的二进制机构存储
-
zibytes 当前存储多少数据
-
zltail 尾节点位置(索引)
-
zllen ziplist存在多少个元素
-
zled:255 标识数据结尾
-
entry
- prerawlen 诺前数据项小于254,则占用1 byte 否则占用标记位+4 byte 即5byte 表示前一个数据的长度
- len 用于表示数据的长度等等
- data 实际存储数据
可用设置
- hash-max-ziplist-entries 512 // 在hash类型ziplist 元素个数超过 512 ,将改为hashtable编码
- hash-max-ziplist-value 64 // 在hash类型单个元素大小超过 64 byte时,将改为hashtable编码
该编码在hash,list中使用
intset
用于存储可以用整型表示的数据,使用该数据编码时,数据有序且唯一,查询数据采用二分查找O(log n) 时间复杂度查询,据存储会根据数据的最大值进行限制和升级,但是只能存储int类型数据
可用设置
- set-max-intset-entries 512 //set类型 intset 能存储的最大元素个数,超过则用hashtable编码
skiplist(跳表)
- header 头节点 记录层级 即索引层
- tail 位节点 用于从后往前遍历
- length 数据数量
- level 跳表层高 开始遍历层
- forward 数据层级 越多就表示代表的层级越多,直接存在节点上,而该层级的数量是根据随机函数进行生产的(越高的层级生成可能越低,越低的层级生成可能越高),如果生成的层级大于最大层级就会更新最大层级
- 数据是直接存储在节点上的
可用设置
-
zset-max-ziplist-entries 128 // zset类型元素个数超过128 ,将用skiplist编码
-
zset-max-ziplist-value 64 // zset类型单个元素大小超过 64 byte, 将用 skiplist编码
embstr
用于针对CPU缓存行优化,每次拿取64byte,而每次获取redisObject只有16byte,sds占用4byte 为了利用剩余空间,在value长度未大于44byte时采用该类型,该类型固定大小长度为64byte
quicklist(双端链表)
当数据存储到一定长度时,为避免数据退化,会进行分裂为多个节点,将在ziplist上添加上层结构
通过设置每个ziplist的最大容量,quicklist的范围数据压缩,提升数据存储效率
-
单个ziplist节点最大能存储8 kb ,超过则进行分裂,将数据存储在新的ziplist节点中,redis.conf中存在说明
list-max-ziplist-size -2
-
节点压缩
list-compress-depth 1
0表示所有节点,都不进行压缩,1表示从头节点走一个,尾节点往前走一个不用压缩,其他的全部压缩,2,3,4…以此类推,中间数据并不频繁访问
该结构在list类型中使用
stream
Redis Stream 是 Redis 5.0 版本新增加的数据结构,该编码是支持stream的
stream详细