Redis学习(2)--list

Redis基础篇–list

list

内部实现: 类似于JAVA的linkedList。列表元素较少时会使用一块连续的内存存储,即ziplist(压缩链表),元素较多时底层是quicklist(快速链表)。可以用来当做异步队列使用。

常见命令:

右边进左边出:队列

rpush books python java golang #从右边(队尾)添加元素
llen books #获取队列的长度
lpop books #从左边弹出元素

右边进右边出:栈

rpush books python java golang #从右边(队尾)添加元素
rpop books #从右边弹出元素

慢操作

lindex books 1 #O(n)慎用 相当于java链表的get(int index)方法,需要对链表进行遍历
lrange books 0 -1 #获取所有元素,O(n),慎用
ltrim books 1 -1 #O(n),慎用 表示只保留下标为1及以上的区间内容
ltrim books 1 0 #相当于清空了整个列表,因为区间长度为负
内部实现
struct ziplist<T>{
	int32	zlbytes;        /* 整个压缩列表占用字节数 */
	int32	zltail_offset;  /* 最后一个元素距离压缩列表起始位置的偏移量,用于快速定位到最后一个节点 */
	int16	zllength;       /* 元素个数 */
	T[] entries;            /* 元素内容列表,依次紧凑存储 */
	int8 zlend;             /* 标志压缩列表的结束,值恒为0xFF */
}
struct entry {
	int<var>	prevlen;        /* 前一个entry的字节长度,一个变长的整数,当字符串长度小于254(即0xFE)时,使用一个字节表示;否则使用5个字节.第一个字节是0xFE,剩余四个字节表示字符串长度 */
	int<var>	encoding;       /* 元素类型编码 */
	optional	byte[] content; /* 元素内容 */
}

在这里插入图片描述

encoding 字段存储了元素内容的编码类型,ziplist通过这个字段来决定后面的content的形式,redis为了节约存储空间,对encoding字段进行了相当复杂的设计。Redis通过这个字段的前缀位来识别具体存储的数据类型.

1.00xxxxxx是最大长度位数为63的短字符串,后面的6个位存储字符串的位数,剩余的字节就是字符串的内容
2.01xxxxxx xxxxxxxx是中等长度的字符串,后面14个位来表示字符串的长度,剩余的字节就是字符串的内容
3.10000000 aaaaaaaa bbbbbbbb cccccccc dddddddd 是特大字符串,需要使用额外4个字节来表示长度。第一个字节前缀是10,剩余6位没有使用,统一置为0.后面跟着字符串内容,不过这样的大字符串是没有机会使用的,压缩列表通常只是用来存储小数据的。
4.11000000表示int16,后跟两个字节表示整数
5.11010000表示int32,后跟四个字节表示整数
6.11100000表示int64,后跟八个字节表示整数
7.11110000表示int24,后跟三个字节表示整数
8.11111110表示int8,后跟一个字节表示整数
9.11111111表示ziplist的结束,也就是zlend的值0xFF
10.1111xxxx表示极小整数,xxxx的范围只能是(0001-1101),也就是1-13,因为0000,1110,1111都被占用了。读取到的value需要将xxxx-1,也就是说整数0-12就是最终的value

intset 小整数集合

当set集合容纳的元素都是整数并且元素个数较少时,redis会使用intset来存储集合元素。
intset是紧凑的数组结构,同时支持16位、32位和64位整数

struct intset<T>{
	int32	encoding;       /* 决定整数位宽是16位、32位还是64位 */
	int32	length;         /* 元素个数 */
	int<T>	contents;       /* 整数数组,可以是16位、32位和64位 */
}

ps: redis早期使用的是压缩链表ziplist和普通的双向链表linkedlist,也就是说当元素少时用ziplist,当元素多时用linkedlist。考虑到链表的附加空间相对太高,pre和next指针就要占用16个字节(64位的操作系统的指针占8个字节),另外每个节点的内存都是单独分配,会加剧内存的碎片化,影响内存管理效率。后来Redis对列表结构进行了改造,使用quicklist代替了ziplist和linkedlist

在这里插入图片描述

struct ziplist {
}
struct ziplist_compressed {
	int32 size;
	byte[] compressed_data;
}

struct quicklistNode {
	quicklistNode	* prev;
	quicklistNode	* next;
	ziplist		* zl;           /* 指向压缩列表 */
	int32		size;           /* ziplist的字节总数 */
	int16		count;          /* ziplist的元素数量 */
	int2		encoding;       /* 存储形式2bit,原生字节数组还是LZF压缩存储 */
}

struct quicklist {
	quicklistNode	* head;
	quicklistNode	* tail;
	long		count;          /* 元素总数 */
	int		nodes;          /* ziplist节点的个数 */
	int		compressDepth;  /* lzf算法压缩深度 */
}

redis对ziplist进行压缩,使用LZF算法压缩,可以选择压缩深度。
quicklist内部默认单个ziplist长度为8KB,超过了这个字节数,就会另起一个ziplist。ziplist的长度由配置参数list-max-ziplist-size决定。

压缩深度

quicklist默认的压缩深度是0,也就是不压缩。压缩的实际深度由
配置参数list-compress-depth决定。为了支持快速的push/pop操作,
quicklist的首尾两个ziplist不压缩,此时压缩深度就是1.
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值