Redis 设计与实现[2] -- 单机数据库的实现

2018/08/14 WEB开发 Java-Web Redis

《Redis 设计与实现》读书笔记

索引

Redis 设计与实现[1] – 数据结构与对象

Redis 设计与实现[2] – 单机数据库的实现

Redis 设计与实现[3] – 多机数据库的实现

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
  • 还原数据结构
  • 执行事件循环

命令从发送到完成:

  • 客户端将命令请求发送给服务器
  • 服务器读取命令请求,并分析出命令参数
  • 命令执行器根据参数查找命令的实现函数,然后执行实现函数并得出命令回复
  • 服务器将命令回复返回给客户端

Search

    Table of Contents