总结:redis中redisDB数据结构和list数据结构以及java中的ArrayList和LinkList的数据结构

9 篇文章 1 订阅
4 篇文章 0 订阅

RedisDB主体
其实就是采用dict字典结构
请添加图片描述
其中redis中的键值对中的键为字符串类型,而在redis中字符串默认为sds,值的类型可以为string,hash,list,set,zset.

Redis

String
本人有篇博客为redis中的字符串与java中的字符串中提及到了。
但是,redis3.2后,对其进行一次优化,
在sds数据结构中多了一个字段 unsigned char flags;占1个字节,其中只用了3位,其他5位没有用,
000:SDS_TYPE_5 表示范围在2^5-1
001:SDS_TYPE_8 表示范围在2^8-1
010:SDS_TYPE_16 表示范围在2^16-1
011:SDS_TYPE_32 表示范围在2^32-1
100:SDS_TYPE_64 表示范围在2^64-1
list
redis 中 list 的底层实现之一是双向链表,该结构支持顺序访问,并提供了高效的元素增删功能。底层采用的是quicklist(双端链表) 和 ziplist
ziplist:
请添加图片描述
ziplist是一块连续的内存空间,元素之间紧挨着存储,没有任何冗余空隙。它的设计目标就是为了提高存储效率。ziplist可以用于存储字符串或整数,其中整数是按真正的二进制表示进行编码的,而不是编码成字符串序列。它能以O(1)的时间复杂度在表的两端提供push和pop操作。

struct ziplist<T> {
  int32 zlbytes;   
  int32 zltail_offset; 
  int16 zllength; 
 T[] entries; 
 int8 zlend; 
}

各部分的含义如下:

zlbytes:整个压缩列表占用字节数,包含本身
zltail_offset:最后一个元素距离压缩列表起始位置的偏移量,用于快速定位到最后一个节点,从而可以在ziplist尾部快速的执行push,pop操作
zllength:元素个数,该字段只有16bit所以可以表达的最大值为2^16-1,如果ziplist元素超了该值呢?这里规定,如果zllength小于等于 2^16-2,该字段表示为ziplist中元素的个数,否则想知道ziplist长度需要遍历整个ziplist
entries:元素内容列表,挨个挨个紧凑存储
zlend:ziplist最后一个字节,标志压缩列表的结束,值恒为 0xFF(255)
压缩列表为了支持双向遍历,所以才会有 ztail_offset 这个字段,用来快速定位到最后一个元素,然后倒着遍历。

struct entry{

int<var> prevlen;           //前一个 entry 的长度

int<var> encoding;          //元素类型编码

optional byte[] content;    //元素内容

}

quicklist:
当链表entry数据超过512、或单个value 长度超过64,而Redis3.2及其之后则采用quicklist结构。
请添加图片描述
情况一: 当 ziplist 节点过多的时候,quicklist 就会退化为双向链表。效率较差;效率最差时,一个 ziplist 中只包含一个 entry,即只有一个元素的双向链表。(增加了查询的时间复杂度)

情况二:当 ziplist 元素个数过少时,quicklist 就会退化成为 ziplist,最极端的时候,就是 quicklist 中只有一个 ziplist 节点。(当增加数据时,ziplist 需要重新分配空间)

所以说:quicklist 其实就是综合考虑了时间和空间效率引入的新型数据结构。(使用 ziplist 能提高空间的使用率,使用 linkedlist 能够降低插入元素时的时间)
quickList的数据结构:
typedef struct quicklist {
//指向头部(最左边)quicklist节点的指针
quicklistNode *head;

//指向尾部(最右边)quicklist节点的指针
quicklistNode *tail;

//ziplist中的entry节点计数器
unsigned long count;        /* total count of all entries in all ziplists */

//quicklist的quicklistNode节点计数器
unsigned int len;           /* number of quicklistNodes */

//保存ziplist的大小,配置文件设定,占16bits
int fill : 16;              /* fill factor for individual nodes */

//保存压缩程度值,配置文件设定,占16bits,0表示不压缩
unsigned int compress : 16; /* depth of end nodes not to compress;0=off */

} quicklist;

fill成员对应的配置:list-max-ziplist-size -2
当数字为负数,表示以下含义:
-1 每个quicklistNode节点的ziplist字节大小不能超过4kb。(建议)
-2 每个quicklistNode节点的ziplist字节大小不能超过8kb。(默认配置)
-3 每个quicklistNode节点的ziplist字节大小不能超过16kb。(一般不建议)
-4 每个quicklistNode节点的ziplist字节大小不能超过32kb。(不建议)
-5 每个quicklistNode节点的ziplist字节大小不能超过64kb。(正常工作量不建议)
当数字为正数,表示:ziplist结构所最多包含的entry个数。最大值为 215215。

compress成员对应的配置:list-compress-depth 0
后面的数字有以下含义:
0 表示不压缩。(默认)
1 表示quicklist列表的两端各有1个节点不压缩,中间的节点压缩。
2 表示quicklist列表的两端各有2个节点不压缩,中间的节点压缩。
3 表示quicklist列表的两端各有3个节点不压缩,中间的节点压缩。
以此类推,最大为 216216。

typedef struct quicklistNode {

struct quicklistNode *prev;     //前驱节点指针
struct quicklistNode *next;     //后继节点指针

//不设置压缩数据参数recompress时指向一个ziplist结构
//设置压缩数据参数recompress指向quicklistLZF结构
unsigned char *zl;

//压缩列表ziplist的总长度
unsigned int sz;                  /* ziplist size in bytes */

//ziplist中包的节点数,占16 bits长度
unsigned int count : 16;          /* count of items in ziplist */

//表示是否采用了LZF压缩算法压缩quicklist节点,1表示压缩过,2表示没压缩,占2 bits长度
unsigned int encoding : 2;        /* RAW==1 or LZF==2 */

//表示一个quicklistNode节点是否采用ziplist结构保存数据,2表示压缩了,1表示没压缩,默认是2,占2bits长度
unsigned int container : 2;       /* NONE==1 or ZIPLIST==2 */

//标记quicklist节点的ziplist之前是否被解压缩过,占1bit长度
//如果recompress为1,则等待被再次压缩
unsigned int recompress : 1; /* was this node previous compressed? */

//测试时使用
unsigned int attempted_compress : 1; /* node can't compress; too small */

//额外扩展位,占10bits长度
unsigned int extra : 10; /* more bits to steal for future usage */

} quicklistNode;

当指定使用lzf压缩算法压缩ziplist的entry节点时,quicklistNode结构的zl成员指向quicklistLZF结构
typedef struct quicklistLZF {
//表示被LZF算法压缩后的ziplist的大小
unsigned int sz; /* LZF size in bytes*/
//保存压缩后的ziplist的数组,柔性数组
char compressed[];
} quicklistLZF;

Java

java中的list接口中的ArrayList,LinkList
请看这篇微博
https://blog.csdn.net/m0_37885223/article/details/96377589

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值