Redis设计与实现——AOF持久化
@ Shen Jianan · Monday, Jun 13, 2016 · 3 minute read · Update at Jun 13, 2016

AOF持久化

RDB持久化通过保存键值对来记录数据库,而AOF则通过保存写命令来记录数据库的。写入的命令有特殊的格式,通过文本格式写入,只是在命令中间增加一些固定的协议分隔符。

AOF持久化的实现

AOF持久化的实现分为追加、写入和同步三个步骤。

struct redisServer{
	// ...
	// AOF 缓冲区
	sds aof_buf;
	// ...
}

服务器进程就是一个事件循环,每次结束一个事件循环之前都会调用一个flushAppendOnlyFile函数,考虑是否将aof_buf缓冲区中的内容写入并保存到AOF文件中。

def eventLoop():
	while True:
		# 处理文件事件,接受命令请求,发送命令回复
		# 处理的过程中会有新的内容被追加到aof_buf缓冲区中
		processFileEvents()
		
		# 处理时间事件
		processTimeEvents()
		
		# 考虑是否要将 aof_buf中的内容写入和保存到 AOF 文件中
		flushAppendOnlyFile()

flushAppendOnlyFile函数的行为由服务器配置的appendfsync选项值来决定。可以是always、everysec或者no,在将aof_buf缓冲区中所有内容写入之后,分别采取:立即同步文件、距离上次写入超过1秒钟间隔的时候同步文件和由操作系统决定同步文件,默认为everysec。

AOF文件的载入与数据还原

服务器使用AOF重建数据库只要重新读入并且执行一遍AOF文件中的命令即可。步骤:

  1. 创建一个不带网络连接的伪客户端,因为Redis命令只能在客户端上下文中执行。
  2. 从AOF文件中分析并读取一条写命令
  3. 使用伪客户端执行被读出的写命令
  4. 重复步骤2和步骤3,知道处理完毕

AOF重写

随着AOF文件中的内容越来越多,文件体积也越来越大,Redis提供AOF重写功能来精简AOF文件。

AOF重写的原理

文件重写不需要读取现有的AOF文件,只需要读取服务器当前的数据库状态,然后直接写入完成相同效果的命令到新的AOF文件中,用新的AOF文件替换旧的AOF文件。相当于将RDB文件转换为AOF文件。在处理有多个元素的键时,会检查是否超过了redis.h/REDIS_AOF_REWRITE_ITEMS_PER_CMD(默认为64)常量的值,如果超过了就分成多条命令执行。

AOF后台重写

AOF重写需要耗费大量的时间,如果直接调用的话,服务器就无法响应其他的请求。所以Redis的AOF重写程序是在子进程里执行的。

使用子进程除了可以让服务器接着处理请求的好处外,还具有自己的数据副本,可以避免使用锁的同时保证数据安全。

为了处理在AOF文件重写之后与最新的AOF文件不一致的情况,Redis服务器设置了一个AOF重写缓冲区,当服务器执行完一个写命令之后,就同时将命令发送给AOF缓冲区和AOF重写缓冲区。

在AOF重写完成之后,服务器调用信号处理函数,将AOF重写缓冲区中的内容写到新的AOF文件中,然后覆盖现有的AOF文件。这时候的信号处理函数就是阻塞的了,因为它是服务器直接调用的。

About Me

2018.02至今 杭州嘉云数据 算法引擎

2017.6-2017.12 菜⻦网络-⼈工智能部-算法引擎

2016.09-2018.06 南京大学研究生

2015.07-2015.09 阿里巴巴-ICBU-实习

2012.09-2016.06 南京大学本科