当前位置: 首页 > 科技观察

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

时间:2023-03-16 22:21:45 科技观察

在Redis中,涉及到的数据结构非常多,比如SDS、双向链表、字典、压缩列表、整数集等等。Redis会根据这些数据结构定制一个对象系统,定制的对象系统有很多好处。通过下面Redis对象系统的学习,我们可以了解Redis的设计原则和初衷,从而在我们使用Redis的时候,更好的理解它的原理和定位问题。Redis对象Redis根据上述数据结构自定义了一个Object系统,Objectstructure:redisObjectstructure:typedefstructredisObject{//typeunsignedtype:4;//encodingunsignedencoding:4;//指向底层数据结构的指针void*ptr;…..}Object系统包含五种Object类型:String:字符串对象List:列表对象Hash:哈希对象Set:集合对象ZSet:有序集合Redis使用对象来表示数据库中的键和值,即每一个newkey值对,至少创建两个对象,使用对象有以下好处:1.Redis在执行命令之前,可以根据对象的类型判断一个对象是否可以执行给定的命令。2.针对不同的使用场景,为对象实现不同的数据结构,优化对象在不同场景下的使用效率。3、对象系统还可以基于引用计数的内存回收机制,自动释放对象占用的内存,或者允许多个数据库键共享同一个对象,以节省内存。4、redis对象有访问时间记录信息,可以用来优化空闲时间大的key,删除!对象的ptr指针指向对象底层真实的数据结构,这些数据结构由对象的encoding属性决定。对应关系:每个Object对象至少有两种不同的编码。对应关系:String对象字符串对象编码可以是int、raw或embstr。如果保存的值是一个整数值,并且这个值可以用long类型表示,使用int编码,其他编码类似。例如:int-encodedStringObjectredis>setnumber520okredis>OBJECTENCODINGnumber"int"StringObject结构:String对象之间的编码转换Int-encodedstring对象和embstr-encodedstring对象在满足条件时会转换为rawEncodedString对象。例如:当对一个int编码的字符串对象执行append命令时,原来的int会变成一个raw编码的字符串List对象。list对象可以是ziplist或linkedlist,对应底层实现。Ziplist是压缩列表,linkedlist是双向列表。Redis>RPUSHnumbers"Ccww"5201Listobjectstructureencodedwithziplist:Listobjectstructureencodedwithlinkedlist:List对象的编码转换:当list对象可以同时满足以下两个条件时,list对象使用ziplist编码:1列表对象中存储的所有字符串元素的长度都小于64字节。2、list对象存储的元素个数小于512,不能满足这两个条件的list对象需要使用链表编码。Hash对象Hash对象的编码可以是ziplist或hashtable。其中,ziplist底层是通过压缩列表实现的:存储相同键值对的两个节点相邻,键在前,值vaule在后。首先保存的key-value对在压缩列表的header方向,在tail方向是通过hashtable底层的字典实现的。Hash对象的每一个键值对存储在一个字典键值对中:字典的key是一个字符串对象,key保存的key字典的值也是一个字符串对象,保存的是value的键值对。例如:HSET命令redis>HSETauthorname"Ccww"(integer)redis>HSETauthorage18(integer)redis>HSETauthorsex"male"(integer)ziplist底层结构:hashtable底层结构:Hash对象编码转换:当list对象可以同时满足以下两个条件,列表对象使用ziplist编码:1.列表对象中存储的所有字符串元素的长度小于64字节2.列表对象中存储的元素个数小于512不能满足这两个条件的hash对象需要使用hashtable编码entriesSet对象:Set对象的编码可以是intset或hashtableintset编码:使用整数set作为底层实现,set对象包含的所有元素都存储在intsetintegersetHashtable编码:使用字典作为底层实现,字典keykey包含一个集合元素和字典的值都是nullinsetencoding集合对象结构:redis>SADnumber135hashtableencoding集合对象结构:redis>SADDfruits"apple""banana""cherry"Set对象的编码转换:使用intset编码:1.set对象保存的所有元素都是整数值2.set对象保存的元素个数不超过512不能满足这两个条件的Set对象使用hashtable编码ZSet对象ZSet对象的编码可以是ziplist或skiplistziplist编码。每个集合元素由两个相邻的压缩列表节点保存,一个为元素成员,一个为元素分数,然后将ziplist编码后的ZSet按照分数从小到大排序对象结构:Redis>ZADDprice8.5apple5.0banana6.0cherryskiplist编码ZSet对象使用zset结构,包括一个字典和一个skip表Typestructzset{Zskiplist*zsl;dict*dict;...}skiplist编码ZSet对象结构ZSet对象编码转换当ZSet对象同时满足以下两个条件时次,对象使用ziplist编码1.有序集合中存储的元素个数小于128个。2.有序集合中存储的所有元素长度小于64字节。以上两个条件不能满足。条件的有序集合对象将使用跳过列表进行编码。注意:可以在配置文件中传入zset-max-ziplist-entries和zset-max-ziplist-vaule