Redis持久化之AOF

Redis提供了2个不同形式的持久化策略:

  • RDB (redis database)
  • AOF (append of file)

这篇文章则记录一下我学习 AOF 过程中的一些笔记,分享给大家。

目录

AOF 模式

1  AOF说明

1.1  何时创建/更新AOF文件

1.2  何时载入和恢复

1.3  持久化实现

2  AOF重写

2.1  AOF何时重写

2.2  AOF文件重写的实现

2.3  AOF后台重写

3  AOF的优缺点


AOF 模式

1  AOF说明

        AOF模式通过保存redis服务器所执行的 写命令 来记录数据库状态。

        Redis默认不开启AOF,需要修改默认配置 appendonly 为 yes:

       下面举个例子,如果我们对数据库执行了以下写命令:

         那么AOF会将服务器执行的SET、SADD、RPUSH三个命令保存在AOF文件中。

        这样,AOF通过保存写操作指令来保存和恢复数据库状态。

1.1  何时创建/更新AOF文件

         Redis允许通过配置 appendonly yes 开启 AOF,如下图。

        Redis允许通过配置 appendfsync 来控制AOF的持久化行为,always是每次执行写操作均写入AOF文件中;everysec是每秒写入一次AOF;no是把何时写入AOF交给操作系统决定,后续会详细说明。

         

1.2  何时载入和恢复

        服务器在启动时,通过载入和执行AOF文件中保存的命令来还原关闭前的数据库状态,以下是服务器载入AOF文件还原数据库的日志:

       读取AOF文件并还原的详细步骤如下:

                (1)创建一个伪客户端,因为Redis命令只能在客户端上下文执行。

                (2)从AOF文件中分析并读取一条写命令。

                (3)使用伪客户端执行。

                (4)loop步骤2、3直到所有写命令处理完毕。

         aof文件名默认为 appendonly.aof,可以通过配置 appendfilename修改:

         aof文件保存路径和rdb相同。

1.3  持久化实现

        AOF持久化功能可以分为①命令追加、②文件写入、③文件同步三个步骤。

       1.3.1  命令追加

        当AOF功能打开时,服务器每执行完一个写操作,会以协议格式将被执行的写命令追加到aof_buf缓冲区的末尾,redisServer结构有一个aof_buf属性,用于保存AOF缓冲:

比如客户端向服务器发送以下指令:

 则以下内容可以追加到aof_buf缓冲区的末尾:

        1.3.2  AOF文件写入和同步

-- 文件的写入和同步

为了提高文件的写入效率,现代操作系统通常有一个内存缓冲区,当用户调用write函数向文件写入数据时,通常将这些内容保存在内存缓冲区里,当缓冲区填满或超过一定的时限后再落盘。

这种做法虽然提高了效率,但是存在数据安全性问题,容易造成数据丢失,因此操作系统提供了fsync和fdatasync同步函数,可以强制立即将缓冲区内容落盘,确保写入数据安全

        redis的服务器进程是一个事件循环,其中文件事件负责接收和响应客户端请求,时间事件负责执行类似serverCron这种需要定时执行的函数。

        由于处理文件事件可能执行写命令,写入aof_buf,因此每次循环结束都会调用flush AppendOnlyFile函数,考虑是否需要将aof_buf缓冲区内容写入和保存到AOF文件。

 

        flushAppendOnlyFile行为由appendfsync选项决定。

         举个例子,假设服务器在处理文件事件期间,执行了3个写命令:

         那么aof_buf缓冲区将包含这三个命令的协议内容:

         当flushAppendOnlyFile函数被调用,且appendfsync为everysec,距离上次同步AOF已经超过1秒,那么服务器会将缓冲区内容写入到AOF文件,然后同步AOF文件。

 

2  AOF重写

        由于AOF是通过保存写命令记录数据库状态。随着服务器运行,AOF文件会越来越大,如果不加以控制,可能会对Redis服务器甚至宿主机造成很大的影响,且AOF文件越大,还原数据所需的时间就越多。

        举个例子,如果客户端执行了下列命令:

        那么为了记录list键的状态,AOF文件需要保存4条指令。

        为了解决AOF文件体积膨胀的问题,Redis实现了文件重写 rewrite 功能。通过创建新AOF文件来代替现有的AOF文件,但是新AOF不会包括浪费空间的冗余命令,只保存最后能恢复数据库状态的指令,如上面4条指令最后只会保存 RPUSH llist "A" "B" "C""C" "D" "E",4条合并成一条。所以新AOF文件的体积通常比旧AOF文件体积小的多。

2.1  AOF何时重写

        redis服务器启动或者上次重写完毕时,服务器会记录此时的AOF大小,设置为base_size,如果服务器当前大小同时满足下面2个条件时,将会进行AOF重写:

                (1)base_size(当前大小) >= base_size + base_size * auto-aof-rewrite-percentage(默认100%)

                (2)base_size(当前大小) >= auto-aof-rewrite-min-size(默认64MB)

        这两个选项可以通过配置修改:

2.2  AOF文件重写的实现

        AOF文件重写不是从旧文件读取分析命令然后写入新文件,而是通过读取当前数据库状态实现的,这有点类似于RDB的快照。

        比如上面执行了4条命令,AOF重写会直接从数据库中读取键llist的值,然后用 RPUSH llist "A" "B" "C""C" "D" "E" 命令来代理原AOF文件中的4条。

        又比如服务器对animals执行了以下命令

        AOF文件需要保存上面列出的4条命令,AOF REWRITE则只用 SADD animals "Dog" "Panda" "Tiger" "Lion" "Cat"来代替上面的4条。整个重写过程如下:

        事实上,为了避免客户端输入输出缓冲区溢出,重写程序在处理List、Hashtable、Set、Zset这四种可能有多个元素的键时,需要检查键包含的值的元素数量,如果超过了REDIS_AOF_REWRITE_ITEMS_PER_CMD(默认为64)时,则会用多条命令来记录键的值,而不是单条。

        比如Set包含的值大于64条时,会如下拆分:

2.3  AOF后台重写

        由于AOF重写时,调用aof_rewrite函数会导致线程被长时间阻塞, 导致服务器不可用,REDIS把AOF重写函数放到子进程中执行。这样可以达到两个目的:

                (1)重写期间,服务器进程可以继续处理客户端请求。

                (2)子进程带有服务器进程的数据副本,使用子进程而不是线程,可以不需要使用锁就能保证数据的安全性。

        但是,子进程重写期间,服务器仍然提供服务,处理客户端请求,这个时间内的写操作又会使得数据不一致。

        为了解决数据不一致的问题,redis设置了AOF重写缓冲区,当REWRITE期间, REDIS服务器执行一个写命令后,同时将这个写命令追加到AOF缓冲区和AOF重写缓冲区。

        这样可以保证:

                (1)AOF缓冲区的内容会定期写入并同步到AOF文件,对现有文件的AOF工作会如常进行。

                (2)从创建子进程开始,服务器执行的所有写命令都会被记录到AOF重写缓冲区里。

        这样即使重写失败,数据也不会丢失。当AOF完成重写工作后,会向父进程(服务器进程)发送一个信号,父进程接收到信号后调用一个信号处理函数,执行以下操作:

                (1)将AOF重写缓冲区内容写入到新AOF文件中,此时新AOF文件保存的数据库状态和当前服务器数据库状态一致。

                (2)对新的AOF文件改名,替代原AOF文件,完成新旧文件的替换。

        在整个重写过程中,父进程只有处理信号函数时会造成阻塞, 其余时间正常提供服务,对服务器造成性能影响降到了最低。

 

3  AOF的优缺点

        优点:

  • 备份机制更加稳健,丢失数据概率较低
  • 备份文件可读,可以进行误操作处理,如不小心flushdb

        缺点:

  •                 比起RDB占用更多的磁盘空间
  •                 备份效率低,存在一定的性能压力

 

        

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值