• 沒有找到結果。

查找元素、根据值定位节点

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 只能用于列表键,而 SADDSRANDMEMBER 只能用于集合 键,等等。

另外一些命令,比如DEL、TTL和TYPE ,可以用于任何类型的键,但是,要正确实现这些 命令,必须为不同类型的键设置不同的处理方式:比如说,删除一个列表键和删除一个字符串 键的操作过程就不太一样。

以上的描述说明,Redis 必须让每个键都带有类型信息,使得程序可以检查键的类型,并为它 选择合适的处理方式。

另外,在前面介绍各个底层数据结构时有提到,Redis 的每一种数据类型,比如字符串、列表、

有序集,它们都拥有不只一种底层实现(Redis 内部称之为编码,encoding),这说明,每当对 某种数据类型的键进行操作时,程序都必须根据键所采取的编码,进行不同的操作。

比如说,集合类型就可以由字典和整数集合两种不同的数据结构实现,但是,当用户执行 ZADD 命令时,他/她应该不必关心集合使用的是什么编码,只要 Redis 能按照ZADD 命令的

为了解决以上问题,Redis 构建了自己的类型系统,这个系统的主要功能包括:

• redisObject 对象。

• 基于 redisObject 对象的类型检查。

• 基于 redisObject 对象的显式多态函数。

• 对 redisObject 进行分配、共享和销毁的机制。

以下小节将分别介绍类型系统的这几个方面。

Note: 因为 C 并不是面向对象语言,这里将 redisObject 称呼为对象一是为了讲述的方便,

二是希望通过模仿 OOP 的常用术语,让这里的内容更容易被理解,redisObject 实际上是只 是一个结构类型。