2.2 压缩列表
2.2.8 查找元素、根据值定位节点
| p
| |
V V
+---+---+---+---+---+---+---+
| ZIPLIST | | | | | | ZIPLIST |
| ENTRY | e1 | e2 | ... | eN-1 | eN | ENTRY |
| HEAD | | | | | | END |
+---+---+---+---+---+---+---+
2.2.8 查找元素、根据值定位节点
这两个操作和遍历的原理基本相同,不再赘述。
2.2.9 小结
• ziplist 是由一系列特殊编码的内存块构成的列表,它可以保存字符数组或整数值,它还是 哈希键、列表键和有序集合键的底层实现之一。
• ziplist 典型分布结构如下:
area |<---- ziplist header ---->|<--- entries --->|<-end->|
size 4 bytes 4 bytes 2 bytes ? ? ? ? 1 byte
+---+---+---+---+---+---+---+---+
component | zlbytes | zltail | zllen | entry1 | entry2 | ... | entryN | zlend | +---+---+---+---+---+---+---+---+
^ ^ ^
address | | |
ZIPLIST_ENTRY_HEAD | ZIPLIST_ENTRY_END
|
ZIPLIST_ENTRY_TAIL
• ziplist 节点的分布结构如下:
area |<--- entry --->|
+---+---+---+---+
component | pre_entry_length | encoding | length | content | +---+---+---+---+
• 添加和删除 ziplist 节点有可能会引起连锁更新,因此,添加和删除操作的最坏复杂度为 O(N2) ,不过,因为连锁更新的出现概率并不高,所以一般可以将添加和删除操作的复 杂度视为 O(N ) 。
56 Chapter 2. 内存映射数据结构
第 3 章
Redis 数据类型
既然 Redis 的键值对可以保存不同类型的值,那么很自然就需要对键值的类型进行检查以及多 态处理。
为了让基于类型的操作更加方便地执行,Redis 创建了自己的类型系统。
在这一部分,我们将对 Redis 所使用的对象系统进行了解,并分别观察字符串、哈希表、列表、
集合和有序集类型的底层实现。
3.1 对象处理机制
在 Redis 的命令中,用于对键(key)进行处理的命令占了很大一部分,而对于键所保存的值的 类型(后简称“键的类型” ),键能执行的命令又各不相同。
比如说,LPUSH 和 LLEN 只能用于列表键,而 SADD 和 SRANDMEMBER 只能用于集合 键,等等。
另外一些命令,比如DEL、TTL和TYPE ,可以用于任何类型的键,但是,要正确实现这些 命令,必须为不同类型的键设置不同的处理方式:比如说,删除一个列表键和删除一个字符串 键的操作过程就不太一样。
以上的描述说明,Redis 必须让每个键都带有类型信息,使得程序可以检查键的类型,并为它 选择合适的处理方式。
另外,在前面介绍各个底层数据结构时有提到,Redis 的每一种数据类型,比如字符串、列表、
有序集,它们都拥有不只一种底层实现(Redis 内部称之为编码,encoding),这说明,每当对 某种数据类型的键进行操作时,程序都必须根据键所采取的编码,进行不同的操作。
比如说,集合类型就可以由字典和整数集合两种不同的数据结构实现,但是,当用户执行 ZADD 命令时,他/她应该不必关心集合使用的是什么编码,只要 Redis 能按照ZADD 命令的
为了解决以上问题,Redis 构建了自己的类型系统,这个系统的主要功能包括:
• redisObject 对象。
• 基于 redisObject 对象的类型检查。
• 基于 redisObject 对象的显式多态函数。
• 对 redisObject 进行分配、共享和销毁的机制。
以下小节将分别介绍类型系统的这几个方面。
Note: 因为 C 并不是面向对象语言,这里将 redisObject 称呼为对象一是为了讲述的方便,
二是希望通过模仿 OOP 的常用术语,让这里的内容更容易被理解,redisObject 实际上是只 是一个结构类型。