Redis中AOF持久化

Redis中除了提供了RDB持久化以外,还提供了AOF持久化 (append-only file)。RDB持久化是把键值对保存在RDB文件中,AOF是把服务器中执行的命令(SET, SADD, RPUSH等)保存在AOF文件中。要恢复时,服务器通过载入和执行AOF文件中保存的命令来还原服务器关闭时的数据库状态。与RDB文件相比,AOF文件一般比较大,而且恢复速度比较慢。但是好处是相对的,因为RDB是每隔一段时间持久化,如果在这期间发生了故障,会丢失很多数据。

AOF持久化的实现

AOF持久化分为命令的追加,文件的写入,文件的同步这三个步骤。

  • 命令的追加:

服务器在执行完一个写命令时,会将被执行的写命令追加到服务器状态中的aof_buf缓冲区的末尾。

struct redisServer
{
    ...
    sds aof_buf;
    ...}
  • AOF文件的写入:

redis 的服务器进程是一个事件循环,这个循环中有文件事件(负责接收客户端的命令请求,以及向客户端发送命令回复),有时间事件(负责执行一些定时函数(如RDB中的serverCron函数))。每次个循环都要考虑是否执行一个flushAppendOnlyFile(), 以便能够将aof_buff缓冲区中的内容写入和保存到AOF文件中。
写函数是如下实现的(在aof.c文件中):

write(server.aof_fd,server.aof_buf,sdslen(server.aof_buf));

它将server.aof_buf中的数据写到server.aof_fd这个文件描述符里。

这里要特别注意的是,写入并不代表就是立即写入aof这个文件中。这里有两个概念,内核缓冲区进程缓冲区
aof_buf是服务器进程缓冲区的数据,调用write()函数时,是将进程缓冲区的数据写入内核缓冲区中,此时write()函数就返回了,而内核缓冲区的数据什么时候写入磁盘,需要的内核来说了算,通常内核会把要写的数据暂时存在缓冲区中,积累到一定数量后再一 次写入。有时会导致意外情况,比如断电,内核还来不及把内核缓冲区中的数据写道磁盘上,这些更新的数据就会丢失。
现代操作系统这样做是有道理的:因为这样能提高了磁盘的I/O效率(读写磁盘总是十分耗时的)。

  • AOF的文件同步

所以flushAppendOnlyFIle()函数还有个同步的操作,其实是调用了fsync()或者fdatasync()这样的同步函数来将内核缓冲区的数据立即“冲洗”到磁盘上。

AOF文件的载入和数据还原

服务器读入AOF文件并重新执行一遍AOF文件里保存的写命令,就可以还原服务器关闭前的数据库状态。这里要注意的是还原时创建的一个不带连接的伪客户端。

AOF文件的重写

随着服务器运行时间的增加,AOF文件中的内容会越来越多,文件体积会越来越大,所以需要提供一个文件重写功能,用一个新的文件,这个文件不包含任何浪费空间的冗余指令,来代替原来的旧文件。这个新文件的体积会小很多。

Redis服务器进程在AOF文件重写时,fork()一个子进程,子进程拥有服务器进程的所有副本,用它来执行文件重写。这样服务器进程还能继续处理其他到来的命令。但是这样会产生一个问题,在子进程执行重写的过程中,服务器也可能执行写文件的操作,这样使得服务器当前数据库状态和AOF文件保存的数据库状态不一致。

为了解决这个问题,在子进程执行重写时,Redis又开启了一个AOF重写缓冲区,将执行的写命令存在这个缓冲区里,当子进程执行完之后,给父进程发送一个信号,父进程又将AOF重写缓冲区的命令追加到新的AOF文件中。

这里写图片描述
最后用新的AOF文件代替旧的AOF文件。重新工作完成。也就是BGREWRITEAOF命令的过程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值