admin管理员组文章数量:1794759
Redis持久化策略——AOF重写优化原理
Redis的持久化方式一共分为RDB持久化与AOF持久化,RDB持久化主要保存数据库状态,即最后数据库中保存的值,而AOF持久化保存的是操作数据库的指令,这时两者的区别就很显而易见,RDB持久化只需要保存很小一部分的值,但是AOF持久化要保存对应的所有操作,而每条Redis操作指令还会被进行加工处理,可想而知,如果要完整保存对数据库表的所有操作,那么这个持久化文件的体积将会很庞大,因此设计者设计过程中实现了AOF重写的优化,本文旨在一步步推进讲解AOF的重写优化策略。
AOF重写实现的初步原理
其实AOF重写实现的原理很简单,比如我执行了一下几条指令的操作:
如果我们按照预期进行AOF持久化,我们需要保存四条指令,但是其实实际上我们只需要读取animals键对应的值,之后设置一条指令进行插入即可,即:
代码语言:txt复制SADD animals "cat" "dog" "panda" "tiger" "lion"
其实保存这一条指令与保存四条指令的最终执行状态是一样的,就是用一条指令替换以前的多条指令,这就是AOF重写功能的实现,在Redis中主要由aof_rewrite函数实现,通过这个函数生成的新AOF文件只包含还原当前数据库状态必须的指令,因此新的AOF文件不会浪费任何硬盘空间
AOF重写功能的优化
一般的AOF重写程序aof_rewrite函数可以很好地完成创建新AOF文件的任务,但是如果仅仅通过这个命令进行AOF持久化,由于大量的写入操作,会导致调用这个线程的函数被长时间阻塞,而Redis服务器又实用单个线程来处理命令请求,所以如果调用aof_write函数会导致服务端无法处理客户端发来的其他命令请求
很明显,Redis不希望AOF重写造成服务器无法继续处理请求,所以Redis将AOF重写程序放到子进程里面执行,也就是AOF后台重写,在Redis中为BGREWRITEOF命令,这样做可以实现两个目的:
1、继续处理命令请求:子进程进行AOF期间,服务器进程(父进程)可以继续处理命令请求
2、保证数据安全性:子进程带有服务器进程的数据副本,使用子进程而不是线程,可以在避免使用锁的情况下,保证数据的安全性
但是这时又出现了一个新问题:如果服务器在子进程进行AOF重写过程中又有新的命令执行,那么又如何保证AOF文件的正确性呢?
为此Redis服务器设置了一个AOF重写缓冲区,在子进程执行AOF命令期间,如果Redis服务器又收到了新命令,那么它会将这个写命令同时发送到AOF缓冲区与AOF重写缓冲区中,而当子进程完成了AOF重写工作后,它会向父进程发送信号,父进程收到信号后会执行一个信号处理函数,执行以下工作:
1)将AOF重写缓冲区中的所有内容写到新AOF文件中,这时新AOF文件所保存的数据库状态将与服务器当前的数据库状态保持一致
2)对新的AOF文件进行改名,原子地(atomic)覆盖现有的AOF文件,完成新旧两个AOF文件的切换
下表展示了一个示例AOF文件后台重写的执行过程:
时间 | 服务器进程(父进程) | 子进程 |
---|---|---|
T1 | SET k1 v1 | |
T2 | SET k2 v2 | |
T3 | SET k3 v3 | |
T4 | 创建子进程执行AOF文件重写 | 开始AOF文件重写 |
T5 | SET k2 10086 | 执行重写操作 |
T6 | SET k3 12345 | 执行重写操作 |
T7 | 执行命令SET k4 22222 | 完成AOF文件重写,向父进程发送信号 |
T8 | 接收到子进程发来的信号,将命令SET k2 10086、SET k3 12345、SET k4 22222追加到新AOF文件的末尾 | |
T9 | 用新AOF文件覆盖旧AOF文件 |
这样通过BGREWRITEOF命令,Redis服务器就将原本一直阻塞服务器线程的时间,压缩为了只需要执行信号处理程序的时间,提高了Redis服务器处理命令的效率
至此,这就是AOF重写优化的全部内容了,希望对你有所帮助!!!
本文标签: Redis持久化策略AOF重写优化原理
版权声明:本文标题:Redis持久化策略——AOF重写优化原理 内容由林淑君副主任自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.xiehuijuan.com/baike/1754862456a1707460.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论