其中,单个字符串不能超过64字节,是为了便于一致分配每个节点的长度;这里的64字节是指字符串的长度,不包括SDS结构,由于紧缩列表运用延续、定长内存块存储字符串,不需求SDS结构指明长度。前面提到紧缩列表,也会强调长度不超过64字节,原理与这里相似。
3、哈希
(1)概略
哈希(作为一种数据结构),不只是redis对外提供的5种对象类型的一种(与字符串、列表、集合、有序结兼并列),也是Redis作为Key-Value数据库所运用的数据结构。为了阐明的方便,在本文前面当运用“内层的哈希”时,代表的是redis对外提供的5种对象类型的一种;运用“外层的哈希”代指Redis作为Key-Value数据库所运用的数据结构。
(2)外部编码
内层的哈希运用的外部编码可以是紧缩列表(ziplist)和哈希表(hashtable)两种;Redis的外层的哈希则只运用了hashtable。
紧缩列表前面已引见。与哈希表相比,紧缩列表用于元素个数少、元素长度小的场景;其优势在于集中存储,节省空间;同时,虽然关于元素的操作复杂度也由O(n)变为了O(1),但由于哈希中元素数量较少,因此操作的时间并没有清楚优势。
hashtable:一个hashtable由1个dict结构、2个dictht结构、1个dictEntry指针数组(称为bucket)和多个dictEntry结构组成。
正常状况下(即hashtable没有停止rehash时)各部分关系如下图所示:
图片改编自:《Redis设计与完成》下面从底层向上依次引见各个部分:
dictEntry
dictEntry结构用于保存键值对,结构定义如下:
typedef struct dictEntry{
void *key;
union{
void *val;
uint64_tu64;
int64_ts64;
}v;
struct dictEntry *next;
}dictEntry;
其中,各个属性的功用如下:
key:键值对中的键;
val:键值对中的值,运用union(即共用体)完成,存储的内容既能够是一个指向值的指针,也能够是64位整型,或无符号64位整型;
next:指向下一个dictEntry,用于处置哈希抵触成绩
在64位系统中,一个dictEntry对象占24字节(key/val/next各占8字节)。
bucket
bucket是一个数组,数组的每个元素都是指向dictEntry结构的指针。redis中bucket数组的大小计算规则如下:大于dictEntry的、最小的2^n;例如,假设有1000个dictEntry,那么bucket大小为1024;假设有1500个dictEntry,则bucket大小为2048。
dictht
dictht结构如下:
typedef struct dictht{
dictEntry **table;
unsigned long size;
unsigned long sizemask;
unsigned long used;
}dictht;
其中,各个属性的功用阐明如下:
table属性是一个指针,指向bucket;
size属性记载了哈希表的大小,即bucket的大小;
used记载了已运用的dictEntry的数量;
sizemask属性的值总是为size-1,这个属性和哈希值一同决议一个键在table中存储的位置。
dict
普通来说,经过运用dictht和dictEntry结构,便可以完成普通哈希表的功用;但是Redis的完成中,在dictht结构的下层,还有一个dict结构。下面阐明dict结构的定义及作用。
dict结构如下:
typedef struct dict{
dictType *type;
void *privdata;
dictht ht[2];
int trehashidx;
} dict;
其中,type属性和privdata属性是为了顺应不同类型的键值对,用于创立多态字典。
ht属性和trehashidx属性则用于rehash,即当哈希表需求扩展或收缩时运用。ht是一个包含两个项的数组,每项都指向一个dictht结构,这也是Redis的哈希会有1个dict、2个dictht结构的缘由。通常状况下,一切的数据都是存在放dict的ht[0]中,ht[1]只在rehash的时分运用。dict停止rehash操作的时分,将ht[0]中的一切数据rehash到ht[1]中。然后将ht[1]赋值给ht[0],并清空ht[1]。
因此,Redis中的哈希之所以在dictht和dictEntry结构之外还有一个dict结构,一方面是为了顺应不同类型的键值对,另一方面是为了rehash。
(3)编码转换
如前所述,Redis中内层的哈希既能够运用哈希表,也能够运用紧缩列表。
只要同时满足下面两个条件时,才会运用紧缩列表:
哈希中元素数量小于512个;
哈希中一切键值对的键和值字符串长度都小于64字节。
假设有一个条件不满足,则运用哈希表;且编码只能够由紧缩列表转化为哈希表,反方向则不能够。
下图展现了Redis内层的哈希编码转换的特点:
(责任编辑:admin)