《Redis设计与实现》笔记3
更新日期:
AOF持久化
与RDB持久化通过保存键值对不同,AOF是通过保存redis服务器所执行的命令来纪录数据库状态的。
AOF持久化分为三个部分:命令追加、文件写入、文件同步
命令追加
redis在AOF持久化打开时,服务器执行完一个写命令后,会将写命令追加到服务器状态的aof_buf缓冲区的结尾。
文件写入
- redis服务器其实就是一个事件驱动程序,它分为文件事件和时间事件。本质上其实就是一个loop事件循环。
- 循环中的文件事件负责接受客户端的命令请求,而时间事件就是执行需要定时运行的函数。
- redis在执行写入和保存操作是执行的flushAppAppendOnlyFile函数,此函数会在事件结束之前考察是否将aof_buf缓冲区中的内容写入和保存到aof文件中。
文件同步
- flushAppAppendOnlyFile函数会执行同步操作,所谓文件同步操作是指:–>在操作系统中,文件内容保存可以分为:文件写入和同步,两个步骤。
操作系统os的系统函数write是将内容先保存到一个内存缓冲区中,等到内存缓冲区被填满或者超过时限之后,才将缓冲区中的内容写到磁盘,这样设计好处是减少磁盘io,换来执行效率。但同时带来了安全隐患,当宕机时缓冲区数据会丢失。所以redis用同步函数fsync和fdatasync来保证数据安全性,使用appendfsync配置项来控制。- appendfsync配置参数是来配置同步频率的,默认为everysec。
2.1. always:实时同步aof文件
2.2. everysec:每秒钟由redis启动一个专门的线程负责执行aof文件同步操作
2.3. no:redis不对aof文件同步频率进行干涉,这里同步频率完全由操作系统自己来决定.- 在同步效率和安全上来讲:三种配置always效率最差,因为每个命令在写操作之后都要进行一次同步,而no最快但是在某个单次操作(当缓冲区累计到达到同步标准的数据时)却是最慢的,。对于安全则反之。从平摊来看no 和 everysec效率相当。
AOF文件载入与还原
- AOF还原时会创建一个不带网络的伪客户端(AOF保存的写命令所以必须要有客户端来执行才行),
- 从AOF文件中读取一条写命令
- 使用伪客户端执行命令
- 重复2,3步骤直至aof文件被执行完。
AOF重写机制
为什么会有重写机制:AOF文件由于纪录了客户端所有执行的写命令(并且是按照时间线记录了写命令),所以aof随时间的积累会越来越大,这样会造成还原时间长,并对原服务器也会造成一定影响。
- 值得注意:虽然叫aof重写但是,并不会对远aof文件执行任何读取、分析或者写入操作。这个功能通过读取服务器当前数据库状态来实现的
比如sadd:就是用smembers key命令来读取key下的所有value,然后将返回的结果用一条sadd来重新组织。- 重写函数简单逻辑:重写函数会遍历所有数据库并忽略空数据库,遍历所有key并忽略过期key。然后取出key对应的value,重新组织一条批量添加命令。
- 重写函数由于会执行大量写入操作,这时会造成服务器堵塞。为了避免堵塞,redis启用子进程来处理rewrite操作。
- 但是单独启用子进程执行时,新的执行写入命令只会修改当前数据库状态,rewrite时的数据库状态不会被修改。
- 为了避免rewrite子进程出现启动遗漏新的redis命令,redis服务器设置了一个aof重写缓冲区,在重写子进程开始使用时,redis执行一个写命令会同时将命令发送给aof重写缓冲区。在rewrite子进程处理完aof缓冲区内容后,会继续将临时缓冲区的命令写到aof文件中。
- 在rewrite重写开始时,redis服务器会:
6.1. 执行客户端发来的命令
6.2 将执行后的命令追加到aof缓冲区
6.3 将执行后的命令追加到aof重写缓冲区
6.4 对新的aof文件完成生成操作后,对新aof文件进行改名,并原子性的覆盖现有aof文件,完成新旧文件替换。