原来Redis的五种数据类型数底层结构是这样的

网友投稿 569 2023-05-15

原来Redis的五种数据类型数底层结构是这样的

原来Redis的五种数据类型数底层结构是这样的

在Redis中会涉及很多数据结构,比如SDS,双向链表、字典、压缩列表、整数集合等等。Redis会基于这些数据结构自定义一个对象系统,而且自定义的对象系统有很多好处。

通过对以下的Redis对象系统的学习,可以了解Redis设计原理以及初衷,为了我们在使用Redis的时候,更加能够理解到其原理和定位问题。

Redis 对象

Redis基于上述的数据结构自定义一个Object 系统,Object结构:

redisObject结构:      typedef struct redisObject{     //类型     unsigned type:4;     //编码     unsigned encoding:4;     //指向底层实现数据结构的指针     void *ptr;     …..  }

Object 系统包含五种Object:

String:字符串对象List:列表对象Hash:哈希对象Set:集合对象ZSet:有序集合

Redis使用对象来表示数据库中的键和值,即每新建一个键值对,至少创建有两个对象,而且使用对象的具有以下好处:

1. redis可以在执行命令前会根据对象的类型判断一个对象是否可以执行给定的命令

2. 针对不同的使用场景,为对象设置不同的数据结构实现,从而优化对象的不同场景夏的使用效率

3. 对象系统还可以基于引用计数计数的内存回收机制,自动释放对象所占用的内存,或者还可以让多个数据库键共享同一个对象来节约内存。

4. redis对象带有访问时间记录信息,使用该信息可以进行优化空转时长较大的key,进行删除!

对象的ptr指针指向对象的底层现实数据结构,而这些数据结构由对象的encoding属性决定,对应关系:

每种Object对象至少有两种不同的编码,对应关系:

String对象

字符串对象编码可以int 、raw或者embstr,如果保存的值为整数值且这个值可以用long类型表示,使用int编码,其他编码类似。

比如:int编码的String Object

redis> set number 520  ok  redis> OBJECT ENCODING number "int"

String Object结构:

String 对象之间的编码转换

int编码的字符串对象和embstr编码的字符串对象在条件满足的情况下,会被转换为raw编码的字符串对象。

比如:对int编码的字符串对象进行append命令时,就会使得原来是int变为raw编码字符串

List对象

list对象可以为ziplist或者为linkedlist,对应底层实现ziplist为压缩列表,linkedlist为双向列表。

Redis>RPUSH numbers “Ccww” 520 1

用ziplist编码的List对象结构:

用linkedlist编码的List对象结构:

List对象的编码转换:

当list对象可以同时满足以下两个条件时,list对象使用的是ziplist编码:

1. list对象保存的所有字符串元素的长度都小于64字节

2. list对象保存的元素数量小于512个,

不能满足这两个条件的list对象需要使用linkedlist编码。

Hash对象

Hash对象的编码可以是ziplist或者hashtable

其中,ziplist底层使用压缩列表实现:

保存同一键值对的两个节点紧靠相邻,键key在前,值vaule在后先保存的键值对在压缩列表的表头方向,后来在表尾方向

hashtable底层使用字典实现,Hash对象种的每个键值对都使用一个字典键值对保存:

字典的键为字符串对象,保存键key字典的值也为字符串对象,保存键值对的值

比如:HSET命令

redis>HSET author name  "Ccww" (integer)  redis>HSET author age  18 (integer)  redis>HSET author sex  "male" (integer)

ziplist的底层结构:

hashtable底层结构:

Hash对象的编码转换:

当list对象可以同时满足以下两个条件时,list对象使用的是ziplist编码:

1. list对象保存的所有字符串元素的长度都小于64字节

2. list对象保存的元素数量小于512个,

不能满足这两个条件的hash对象需要使用hashtable编码

Note:这两个条件的上限值是可以修改的,可查看配置文件hash-max-zaiplist-value和hash-max-ziplist-entries

Set对象:

Set对象的编码可以为intset或者hashtable

intset编码:使用整数集合作为底层实现,set对象包含的所有元素都被保存在intset整数集合里面hashtable编码:使用字典作为底层实现,字典键key包含一个set元素,而字典的值则都为null

inset编码Set对象结构:

redis> SAD number  1 3 5

hashtable编码Set对象结构:

redis> SAD Dfruits  “apple”  "banana" " cherry"

Set对象的编码转换:

使用intset编码:

1. set对象保存的所有元素都是整数值

2. set对象保存的元素数量不超过512个

不能满足这两个条件的Set对象使用hashtable编码

ZSet对象

ZSet对象的编码 可以为ziplist或者skiplist

ziplist编码,每个集合元素使用相邻的两个压缩列表节点保存,一个保存元素成员,一个保存元素的分值,然后根据分数进行从小到大排序。

ziplist编码的ZSet对象结构:

Redis>ZADD price 8.5 apple 5.0 banana 6.0 cherry

skiplist编码的ZSet对象使用了zset结构,包含一个字典和一个跳跃表

Type struct zset{      Zskiplist *zsl;     dict *dict;     ... }

skiplist编码的ZSet对象结构

ZSet对象的编码转换

当ZSet对象同时满足以下两个条件时,对象使用ziplist编码

1. 有序集合保存的元素数量小于128个

2. 有序集合保存的所有元素的长度都小于64字节

不能满足以上两个条件的有序集合对象将使用skiplist编码。

Note:可以通过配置文件中zset-max-ziplist-entries和zset-max-ziplist-vaule

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Redis,Nginx,Netty为什么这么香?
下一篇:听说Redis都会遇到并发、雪崩等难题?我用10分钟就解决了
相关文章