最近在读黄健宏的《Redis设计与实现》,看完了第一部分,它是采用的自底向上的介绍方法。从最底层的数据结构开始,逐个介绍所用到的数据结构,最后形成数据库。我准备做个redis的学习笔记,这里我就自顶向下整理一下。
服务器中的数据库
redis服务器将所有数据库保存在服务器状态redis.h/redisServer结构的db数组中,db数组中的每项都是一个redis.h/redisDb的结构体,每个redisDb结构就代表一个数据库。
struct redisServer{
...
// 一个保存着redisDb的数组,db中的每一项就是一个数据库
redisDb *db;
...}
redis是一个键值对数据库,每个数据库由一个redisDb结构表示,其中redisDb结构中的字典dict保存了数据库中所有的键值对。
redisDB结构体的定义
typedef struct redisDb{
...
//保存数据库中所有的键值对
dict *dict;
...}
当我们在客户端输入
redis>SET msg "hello"
OK
时(一般默认是在数据库0中进行,可以通过SELECT切换数据库),其实是创建了两个对象,一个是键字符串对象(因为键总是字符串对象),另一个是值字符串对象(在这里是字符串对象)。
Redis中的对象
在Redis中,是使用对象来表示数据库中的键和值,键总是字符串对象,而值的对象可以是字符串对象,列表对象,哈希对象,集合对象,有序集合对象5种。每个对象由一个redisObject结构表示,该结构中和保存数据有关的三个属性是type,encoding,ptr。
typedef struct redisObject{
unsigned type ;
unsigned encoding;
void *ptr;
...}
类型type表示是上述5中对象中的哪一种,再次强调,键只能是字符串对象(REDIS_STRING)。ptr指针指向对象实现的底层数据结构,encoding表示编码,不同的编码所对应的对象实现的数据结构不同。这些底层数据结构有int, embstr, 简单的动态字符串(SDS), 字典, 双端链表,压缩列表,整数集合,跳跃表,字典等。
数据库存储方式
如前所述,Redis的每一个数据库是由一个redisDb结构表示的,redisDb结构中的dict保存了数据库中所有的键值对,每一个键是一个对象,值也是一个对象。一般将这个字典叫做键空间。
假如创建了一个字符串:
redis>SET message "hello world"
一个列表:
redis>RPUSH alphabet "a" "b" "c"
和一个哈希表:
redis>HMSET book name "Redis in ACtion" author "Josiah L. Carlson" publisher "Manning"
那么数据库的redisDb的存储方式是如下图所示的:
注意dict中每个键都是一个StringObject, 键所对应的值的对象随着存储数据的不同而不同。
book这个哈希表的’name “Redis in ACtion” author “Josiah L. Carlson” publisher “Manning” ’在redisDb中是值,它自己又是个哈希的对象。它可以通过ziplist(压缩列表)来实现,又可以通过字典来实现。相当于“大字典”(键空间)中套“小字典”(哈希对象的字典实现)
对于字典的结构,SDS 的结构,压缩列表的结构,集合或者有序集合的结构将在后面整理。