1、简单动态字符串
简单动态字符串(simple dynamic string, SDS
)是 Redis 的默认字符串表示,是一个可修改的字符串值。Redis 只使用C字符串作为字面量,在大多数情况下,Redis使用SDS作为字符串表示。
STRING 的底层实现之一。
1.1 SDS 的定义
1.2 SDS 的空间预分配
当SDS需要空间拓展时,程序会预先分配SDS一些额外的空间。即当SDS长度(len 属性) < 1MB时,分配和len属性同样大小的未使用空间,当SDS长度(len 属性) >= 1MB时,分配1MB大小的未使用空间。
1.3 SDS 的惰性空间释放
SDS 字符串缩短时用free记录,不实际释放内存。
1.4 SDS 二进制安全
C语言的字符串不能包含 \0
,否则会认为是字符串的结束,因为不能用C语言的字符串保存二进制数据。
而SDS是二进制安全的,可以用来保存任何二进制数据比如图片、序列化对象等等,SDS以len属性判断字符串结尾,程序不会对其中的数据做任何限制或过滤,因此也称SDS的buf是字节数组。
但SDS也会在保存数据的结尾设置为\0
(不占用len和free,buf多分配一字节),这是为了在SDS保存文本数据时可以重用<string.h>
的库函数。
2、链表
列表(LIST) 的底层实现之一。
3、字典
字典是一种保存键值对的抽象数据结构(保存若干键值对)。字典中的每个键都是独一无二的。
Redis 数据库及哈希(HASH) 及集合(SET)的底层实现之一。
3.1 字典的实现
采用拉链法处理冲突,头插法插入。
重点:
Redis 的字典 dict 中包含两个哈希表 dictht,这是为了方便实现渐进式 rehash 操作。在扩容时,将其中一个 dictht 上的键值对渐进地 rehash 到另一个 dictht 上面,这期间发生的查找、删除、更新等操作会分别在两个dictht中找,完成rehash之后释放空间并交换两个 dictht 的角色。
3.2 rehash
linux 的写时复制技术:
在linux程序中,fork()会产生一个和父进程完全相同的子进程,但子进程在此后多会exec系统调用,出于效率考虑,linux中引入了“写时复制”技术,也就是只有进程空间的各段的内容要发生变化时,才将父进程的内容复制一份给子进程。
在fork之后exec之前两个进程用的是相同的物理空间(内存区),子进程的代码段、数据段、堆栈都是指向父进程的物理空间,也就是说,两者的虚拟空间不同,其对应的物理空间是一个。当父子进程中有更改相应段的行为发生时,再为子进程相应的段分配物理空间。
渐进式 rehash
4、跳跃表
有序集合,ZSET 的底层实现之一。跳跃表是基于多指针有序链表实现的,可以看成多个有序链表。
跳跃表查找特定值的时间复杂度为O(logn),他是一种可以代替平衡树的数据结构。
与红黑树等平衡树相比,跳跃表具有以下优点:
- 插入速度非常快速,因为不需要进行旋转等操作来维护平衡性;
- 更容易实现;
- 支持无锁操作。
- 比红黑树更快进行范围查找,因为底层节点相连。
5、整数集合(intset)
contents 数组中的元素类型会自动升级
整数集合不支持降级操作。
6、压缩列表(ziplist)
7、对象
7.1 对象概述
7.2 字符串对象(STRING)
- 如果是整数值,并且这个整数可以用long类型表示,则字符串对象的编码设置为int
- 如果是长度大于32字节的字符串值,则编码设置为raw,使用SDS保存。
- 如果是长度小于等于32字节的字符串值,则使用embstr编码方式保存。
浮点数的处理
embstr 简介
编码的转换
int 编码的字符串对象和embstr编码的字符串对象在条件满足的情况下,会被转换为raw编码的字符串对象。对于int编码的字符串对象来说,如果我们向对象执行了一些命令,使得这个对象保存的不再是整数值,而是一个字符串值,那么字符串对象的编码将从int变成raw。
7.3 列表对象(LIST)
列表对象使用ziplist或linkedlist保存。
字符串对象是Redis五种类型的对象中唯一一种会被其他四种类型对象嵌套的对象。
7.4 哈希对象(HASH)
7.5 集合对象(SET)
7.6 有序集合对象(ZSET)
其中 skiplist 编码同时使用了字典和跳跃表。
- 如果只使用字典,则根据分数查找的复杂度会是O(N) ,范围查找O(NlogN),因为还需要排序。而有跳跃表则变成O(logN)。
- 如果只使用跳跃表,则根据元素查找分数或判断此元素是否存在的复杂度会是O(N),而有字典只需O(1)。
8、内存回收
9、对象共享
Redis 只对包含整数值的字符串对象进行共享。(因为验证操作时间复杂度是O(1))
10、对象的空转时长 (用于LRU算法)