redis学习系列(八)--redis-AOF基础

来源:互联网 发布:mac修改mysql登录密码 编辑:程序博客网 时间:2024/06/05 05:06

redis另外一种持久化方式就是AOF方式(Append Only File)

上一篇 RDB的持久化方式是通过保存键值对来记录数据库状态的不同,AOF持久化不同点在于它不是通过键值对,而是通过保存Redis服务器执行的写命令来记录的。

这样的话感觉在实时性上面,AOF是要优于RDB的,因为这样至少能保证不会丢数据,而RDB方式的话会丢到达到它保存条件中间的一部分数据。

例如:


对于上面的操作过程:

RDB方式:保存的是键值对

AOF方式:保存的是set命令


注意的是,第一行是出现了一个SELECT命令,这是Redis自动添加的,说明这个数据是存在哪一个数据库内的

AOF持久化的实现

AOF持久化功能的实现分为命令追加(append)、文件写入、文件同步(sync)三个步骤

命令追加

当AOF功能打开时,服务器在执行完一个写命令之后,会以协议格式将被执行的命令追加到服务器状态的aof_buf缓冲区的末尾

struct redisServer {        sds aof_buf;      /* AOF buffer, written before entering the event loop */}

AOF文件的写入和同步

这里面讲到一个事件的概念,暂时我还不清楚,不过知道下Redis的服务器进程就是一个事件循环,这个循环中的文件事件负责接收客户端的命令请求,以及向客户端发送命令回复,而另外一个时间事件则负责执行定时运行的函数。

这是因为当服务器在处理文件事件时可能会执行写命令,使得有一些命令被追加到了aof_buf缓冲区里面,因此在一个事件循环结束之前,都会调用flushAppendOnlyFile函数,考虑是否需要将aof_buf缓冲区的内容写入和保存到AOF文件里面

flushAppendOnlyFile函数的行为是受配置项的值决定的



关于AOF持久化的效率和安全性



一般受推荐的配置就是everysec。

AOF文件的载入与数据还原


可见上图中的简单流程图,需要创建一个伪客户端(fake clinet)

AOF重写及实现

AOF是保存命令行的,对比RDB不同,有可能对于一直set操作,RDB最终保存的是键值对,而AOF保存的是set命令,这就造成了,如果你不断的修改set的值,那么最终结果其实只有一个,但是命令却有1000行。那么还原的时间就会越长,相信Redis肯定解决了这个问题,就是重写操作。

例如下面的操作,这一篇就不去改了,下一篇会去着重试验,而且虚拟机出了一点问题,,,只能截图了现在


可以看见对一个list进行了至少5个操作,但是AOF确保存了6条命令,因此Redis提供了重写(rewrite)功能,通过此功能,Redis服务器可以创建一个新的AOF文件来代替现有的AOF文件,新旧两个AOF所保存的数据库状态相同,单新的AOF不会包含冗余命令。

实现

但是重写并不是去读取现有的AOF文件,而是直接从数据库中读取键值对,然后用一条命令去记录键值对,代替之前的多条命令,这就是重写功能的实现原理。


保存之后的状态:可以看见没有一条多余的命令


这边有个实际处理的问题,我也没有实践过,记录一下:

列表、哈希表等集合会有很多元素,当元素数量超过64个时,会将一条命令拆分成两个,至于为什么,不清楚,效率?内存?不懂。

#define REDIS_AOF_REWRITE_ITEMS_PER_CMD 64

AOF后台重写

重写函数aof_rewrite可以很好的完成创建一个新的AOF文件,但是这个函数会大量的进行写入操作,因此会被长时间阻塞,那么Redis不能处理来自客户端的任何请求了,因此在此处也会出现一个子进程用于AOF的重写。

但是考虑下面一个问题,万一在子进程在重写的阶段,父进程一直在处理请求,此时键值对的值改变了,但是子进程怎么知道呢,它读到的数据库内的值可能在它刚读完之后就立马改变了。


为了解决这个问题,Redis设置了一个AOF缓冲区,这个缓冲区在服务器创建子进程之后开始使用,当Redis执行完一个写命令之后,会同时将写命令发送给AOF缓冲区和AOF重写缓冲区。


根据上图可知道一些信息:

1.服务器进程执行客户端发来的命令。

2.将执行后的写命令追加到AOF缓冲区。

3.将执行后的写命令追击到AOF重写缓冲区。

这样能保证几点:

1.AOF缓冲区的内容会定期被写入和同步到AOF文件,对现有AOF文件的处理工作会正常进行,不影响

2.从创建子进程开始,服务器的所有写命令会被记录到AOF重写缓冲区里面,保证写命令不丢失。

当子进程完成AOF重写工作之后:

一旦子进程完成AOF重写之后,会发送一个信号给父进程,父进程处理以下事情:

1.调用信号处理函数(这个函数不知道是什么函数),将AOF重写缓冲区的所有内容写入到新AOF文件中,这保证了新AOF文件所保存的数据库状态和服务器当前的一致。

2.对新AOF文件进行改名,原子地覆盖现有AOF文件,完成交替。

这边注意下,对于AOF重写缓冲区的数据是父进程在子进程完成之后保存的,不是子进程读取写入的,我一开始还天真的以为是子进程边读边写,,,,,


因此看下这边的流程,只有信号处理函数时父进程调用的,当调用它时,才会阻塞父进程。其实我这边我不清楚一个问题,在AOF重写缓冲区里面是不是存储的可能是多条命令,比如set num 1; set num 2;set num 3,这里并没有提到这个问题,应该是这样的,重写的时候读取的是数据库的键值对,但是缓冲区存储的确是命令。


原创粉丝点击