本文总结个人在学习Redis时了解到的结构类型与每种结构底层对应的编码类型 。
Redis对象头
在Redis中,所有的对象都有对象头结构,其结构如下:
本文的内容就是有关于的type和encoding的总结。
Redis结构类型
Redis在使用层面大致有五种结构类型:
- 字符串(string)
- 列表(list)
- 集合(set)
- 哈希(hash)
- 有序集合(zset)
通过命令:help @类型,可以查看对应结构类型的使用命令(注意:zset使用的是help @sorted_set);
通过命令:type key,可以输出key对应的结构类型;
补充:
在Redis5.0中又加入了另外一种结构类型stream,大致是一个支持持久化的多播消息队列,在本文中不做介绍。
Redis编码类型
Redis编码类型是指每种结构类型的底层实现,Redis的每种结构类型根据数据量或数据大小的不同,会使用不同的编码类型,尽可能地节省内存空间以及提高访问性能,以下说明每种结构类型使用到的编码类型。
字符串(string)
字符串对应的编码类型有int、embstr和raw三种,根据值的不同Redis会采用不同的编码
- 当所设置的值是一个long范围内的整数时,会使用int编码;
- 当设置的值是一个长度小于等于44的字符串时,会使用embstr编码;
- 当设置的值是一个长度大于44的字符串时,会使用raw编码;
PS:关于embstr和raw按44字节为分界是在Redis3.2开始的,之前是以39字节为分界的。而44字节字节这个分界是如何确定的呢?还有为什么要把字符串分为embstr和raw,这两者有什么区别呢?有兴趣的可以自行去了解一下,这里不做详细阐述。
注意点:
Redis字符串是一个动态的字符串,在其操作中有个append命令,可在原字符串上追加字符串,不管字符串原先编码类型是什么(int或embstr),通过该操作后,字符串的编码类型都将变为raw类型。
列表(list)
在Redis3.2前,列表对应的编码类型有ziplist和linkedlist,当列表中保存的单个数据小于等于64字节且列表数据个数不超过512个时,使用ziplist,否则使用linkedlist。
在Redis3.2后,列表统一使用了quicklist(其实就是将ziplist和linkedlist结合在一起的一种结构),quicklist的结构如下图(图片来自Redis深度历险):
从上图中可以看出,quicklist大致上还是一个linkedlist结构,只是每个节点存储的不在是单个元素,而是一个ziplist结构。
集合(set)
集合的编码类型有intset和hashtable两种,区分的条件如下:
- 当集合中的元素都为long范围内的整数且元素个数不超过512个(512个为Redis的默认配置,通过配置项set-max-intset-entries配置)时,使用intset;
- 当集合中元素存在非整数或元素超过512个时,使用hashtable
有序集合(zset)
有序集合的编码类型有ziplist和skiplist两种,区分的条件如下:
- 当集合中的元素大小小于等于64字节(通过配置项zset-max-ziplist-value配置)且集合元素个数小于128个(通过配置项zset-max-ziplist-entries配置)时,采用ziplist存储;
- 当不满足以上任一条件时则采用skiplist存储
哈希表(hash)
哈希表的编码类型有ziplist和hashtable两种,区分的条件如下:
- hash的键和值大小小于等于64字节(通过配置项hash-max-ziplist-value配置)且键值对的个数不超过512个(通过配置项hash-max-ziplist-entries配置)时,采用ziplist存储;
- 当不满足以上任一条件时则采用hashtable存储
总结
从上面的介绍中可以看出Redis的每种结构类型至少都采用了两种编码类型,这些编码类型对于使用者来说是透明的,即使用者可以不用理会的;不同编码类型间存在着一个界限,除了字符串外,其他结构类型都提供了配置项用于配置这个界限;Redis每种编码类型其实就是底层的一种数据结构,这些数据结构有很多地方值得学习,后续将继续探索。