欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  数据库

数据类型之 String List

程序员文章站 2024-02-09 17:12:04
...

Redis源码解析4 - 数据类型之 String List STRING string类型的数据在Redis中有两种编码方式: 1.RAW 这表示一个原始字符串对象,robj中的ptr指针指向一个sds类型的内存块 sds是一个带长度信息的内存块,用于存储 二进制安全 的字符串 2. INT 这表示一个编码

Redis源码解析4 - 数据类型之 String & List

STRING

string类型的数据在Redis中有两种编码方式:

1. RAW
这表示一个原始字符串对象,robj中的ptr指针指向一个sds类型的内存块
sds是一个带长度信息的内存块,用于存储二进制安全的字符串

2. INT
这表示一个编码为整数的字符串对象,robj中的ptr指针被强行转化为一个long型变量以存储整数
数字类型的字符串,比如“123456”,都会被编码为整型
这样做的目的就一点,节省内存。就以字符串“123456”为例,
(1) 存为RAW类型,共消耗内存为:sizeof(robj) + sizeof(sdshdr) + strlen("123456")
32位系统为26字节,64位系统下为30字节
(2) 存为INT类型,共消耗内存为:sizeof(robj)
32位系统为12字节,64位系统下为16字节

可以看出,节省的内存还是挺多的
如果字符串更长一些,比如“123456789”,节省的内存就可观了

一点小提示,在Redis中,64位的bigint,香港虚拟主机,是按RAW格式存储的
之所以这么做,完全是为了兼容不同的系统
在实际使用中,如果你确定你的机器都是64位的(MS现在很少32位机了),可以改改源代码,多节省一些内存

再加一幅图,更直观的说明一下

数据类型之 String List

OK,在Redis中,String是最基本的类型,也很简单,从上图可以较清晰的看出String的组织方式了

题外话,不知道有同学注意到没有,robj中的ptr居然是指向sdshdr内存块的中间部分,而不是指向内存头

从这一点看,Redis的代码也挺“野”的

LIST

list数据有两种编码方式:

1. linked_list
这就是一个传统的双向链表,带头尾指针,其头尾操作都只有O(1)的复杂度

2. ziplist
这是一种压缩编码的链表,它将所有的链表数据全部整合进一整块内存中,相比传统的链表,节省很多内存

数据类型之 String List

简要说明一下上图:

(1) ziplist使用一整块连续的内存,这块内存由三部分组成:
(a) head块,链表的头信息,包括有 totalsize(链表总长度)、tailoffset(尾部最后一个元素的偏移字节数)、entrycount(entry个数)
(b) entry块,由一系列的 entry node 组成。node之间紧凑排列
每个node有 prevsize字段,表示前一个node的长度,用以反方向索引
有selfsize字段,表示当前node的长度
以及data字段,存放当前node的实际数据
这些字段都按一种特殊的形式编码,具体参考上图,已经比较清晰了
(c) tail块,虚拟主机,链表的尾部。只有一个字节,是一个填充码。

(2) 向ziplist中增删元素时,有较频繁的内存重分配操作,香港服务器,以及较复杂的数值运算
所以,当链表长度增加时,整个数据结构就会不堪重负

(3) redis用两个阀值来控制 ziplist 与 linked_list 之间的转换
(a) list_max_ziplist_entries:当链表元素的个数超过该值,自动转化为 linked_list,该值默认512
(b) list_max_ziplist_value:当链表中某个字符串元素的长度超过该值,自动转化为 linked_list,该值默认64
(c) 以上两值均可通过配置文件修改

posted on

数据类型之 String List