《Redis 设计与实现》读书笔记
索引
1 键空间
set message "hello word"
rpush alphabet "a" "b" "c"
hset book name "Redis in action"
hset book author "Josian L. Carlson"
hset book publisher "Manning"
执行以上指令后,数据库的键空间如下所示:
2 总结
- Redis 服务器的所有数据都是保存在 redisServer.db 数组中,而数据库的数量则由 redisServer.dnum 属性保存
- 客户端通过修改目标数据库指针,让它指向 redisServer.db 数组中的不同元素来切换数据库
- 数据库主要由 dict 和 expires 两个字典构成,其中 dict 字典负责保存键值对,expires 字典则负责保存键的过期时间
- Redis 使用惰性删除和定期删除两种策略来删除过期的键:惰性删除策略只在碰到过期键时才进行删除操作,定时删除策略则每隔一段时间主动查找并删除过期键
3 持久化
3.1 RDB
RDB 持久化功能所生成的 RDB 文件是一个经过压缩的二进制文件,通过该文件可以还原生成 RDB 文件时的数据库状态。
两个指令可以用于生成 RDB 文件:SAVE 和 BGSAVE
- SAVE 指令会阻塞 Redis 服务器进程,直到 RDB 文件创建完毕为止,在服务器进程阻塞期间,服务器不能处理任何命令请求
- BGSAVE 命令会派生出一个子进程,然后由子进程负责创建 RDB 文件,服务器进程继续处理命令请求
RDB 文件的载入工作是在服务器启动时自动执行的,只要 Redis 服务器在启动时检测到 RDB 文件存在,它就会自当载入 RDB 文件。但是由于 AOF 文件的更新频率通常比 RDB 文件要高,因此服务器会优先使用 AOF 文件来还原数据库状态。
对于一个空的 RDB 文件,将由以下四个部分组成:
- 五个字节的 “REDIS” 字符串
- 四个字节的版本号 (db_version)
- 一个字节的 EOF 常量
- 八个字节的校验和(check_sum)
3.2 AOF
AOF 是通过保存 Redis 服务器所执行的写命令来记录数据库的状态,在读取文件还原数据的时只需要从 AOF 文件中分析并依次读取出每条写命令
AOF 的持久化功能的实现可以分为命令追加,文件写入,文件同步三个步骤
命令追加:当 AOF 持久化功能处于打开状态时,服务器在执行完一个写命令后,会以协议格式将被执行的写命令追加到服务器状态的 aof_buf 缓冲区的末尾
文件写入:关于文件的写入和同步操作,可以使用以下伪代码来描述
def eventLoop():
while True:
# 处理文件事件,接收命令请求以及发送命令回复
# 处理命令请求时可能会有新内容被追加到 aof_buf 缓冲区中
processFileEvents()
# 处理时间事件
processTimeEvents()
# 考虑是否要将 aof_buf 中的内容写入和保存到 AOF 文件里面
flushAppendOnlyFile()
flushAppendOnlyFile 函数的行为由服务器配置的 appendfsync 选项的值来决定,各个不同值产生的行为不同:
always(将缓冲区所有内容写入并同步到 AOF 文件),(将所有内容写入到 AOF 文件并每间隔一秒同步一次),no(及那个内容写入到 AOF 文件,但是同步时间由操作系统决定)
由于 Redis 使用单线程来处理命令请求,如果服务直接调用 aof_rewrite 函数来重写 aof 文件,则服务期间无法处理客户端发来的命令请求,因此,Redis 将 AOF 重写程序放到子进程里执行,其优点如下:
- 子进程进行 AOF 重写期间,服务器进程可以继续处理命令请求
- 子进程带有服务器进程的数据副本,使用子进程而不是线程,可以在避免使用锁的情况下,保证数据的安全性
AOF 后台重写的具体实现如下:
服务器:
- 执行客户端发来的命令
- 将执行后的写命令追加到 AOF 缓冲区
- 将执行后的写命令追加到 AOF 重写缓冲区
子进程在完成 AOF 重写后,会向父进程发送一个信号,父进程接到该信号后会调用一个信号处理函数并执行以下工作:
- 将 AOF 重写缓冲区中的所有内容写到新 AOF 文件中
- 对新的 AOF 文件进行改名,原子地覆盖现有的 AOF 文件,完成新旧两个 AOF 文件的替换
4 客户端和服务器
4.1 客户端
- Redis 是一对多的服务器程序,通过使用由 I/O 多路复用技术实现的文件事件处理器,Redis 服务器使用单线程单进程的方式来处理命令请求,并与多个客户端进行网络通信
- 服务器状态结构使用 clients 链表连接起多个客户端状态,新添加的客户端状态会被放到链表的末尾
4.2 服务器
服务器的启动:
- 初始化服务器状态
- 载入服务器配置
- 初始化服务器数据结构fu
- 还原数据结构
- 执行事件循环
命令从发送到完成:
- 客户端将命令请求发送给服务器
- 服务器读取命令请求,并分析出命令参数
- 命令执行器根据参数查找命令的实现函数,然后执行实现函数并得出命令回复
- 服务器将命令回复返回给客户端