[Redis]Redis持久化之AOF
Redis持久化之AOF
Redis是一个内存数据库管理系统。所谓的内存数据库,就是将数据库中的数据保存在内存当中。内存数据库的读写效率会比一般的数据库更快,但是一旦断电或者宕机,数据库中的数据就会全部丢失。
为了应对数据丢失的问题,Redis提供了将数据持久化到本地的功能,以便对数据进行备份。Redis支持两种形式的数据持久化,一种是RDB快照(snapshotting),另外一种是AOF(append-only-file)。本篇对其中的AOF快照进行讲解。
简介
Redis默认使用RDB将数据保存到磁盘上,这种策略对于大部分系统来说已经足够使用了,但是RDB存在一个问题:如果出现了错误,会丢失上个保存点之后更改的所有数据。对于某些应用程序,这些损失是无法容忍的。所以为了解决RDB的不足,Redis引入了AOF(append-only-file)。
AOF是Redis数据持久化策略中的另一种,它通过不断向文件追加写入Redis的操作来记录数据库里面的数据。这样可以将Redis在出错时损失的数据控制在仅仅一秒内,甚至只损失一次写操作。
AOF将数据写入磁盘的流程如下:
服务器接收到写操作请求,调用write(2)将请求写入内存缓冲区。
Redis或操作系统调用fsync将缓冲区中的数据写入磁盘缓存。
磁盘将缓存中的数据写入物理介质。(大多数磁盘只开启读缓冲,所以写操作会直接写入物理介质)
AOF配置
appendonly no
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
dir ./
appendonly项控制AOF的开关。
appendfilename项控制AOF文件的名字。
-
appendfsync项控制Redis调用fsync的频率。调用fsync会使操作系统将数据完全写入到文件中,而不是放在输出缓冲区里面。appendfsync项支持三种模式:
no:从不调用fsync,由操作系统自行决定什么时候将缓冲区里的数据写入文件。大多数Linux系统是每30秒进行一次。这种模式的速度最快,效率最高,但是不能保证数据安全。
always:每次执行写操作之后都调用fsync。这种模式最慢,但也是最安全的,可以保证出错时最多只损失一次操作。这种模式由于不断地写入少量数据,会严重缩短固态硬盘的寿命。
everysec:每一秒调用一次fsync。是一种折中的方案,也是配置文件的默认值。当fsync调用时长超过一秒时,Redis会延迟下一次fsync的调用到下一秒。
no-appendfsync-on-rewrite项控制当执行重写时是否阻止调用fsync。当调用fsync的时候如果正好在进行后台保存操作或者AOF重写,这时会有大量数据写入缓冲区,在某些情况下会导致阻塞。这个问题目前还没有从根本上得到修复,为了解决这个问题,可以将该项设置为yes,使Redis在执行BGSAVE或者BGREWRITEAOF时阻止调用fsync,不过这可能会导致损失一部分数据。
auto-aof-rewrite-percentage项用于控制AOF文件的自动重写规则。Redis会记录最后一次重写AOF文件后的文件大小(如果没有进行过重写,则记录AOF文件一开始的大小),如果当前AOF文件的大小大于指定的百分比,就会触发一次AOF重写。如果将该值指定为0,则Redis不会自动重写AOF文件。AOF的重写流程跟RDB一样。所以在新的AOF文件完全写入之前发生的写操作,都会写入旧的AOF文件以及缓存中。
auto-aof-rewrite-min-size项用于控制AOF重写的最小文件大小。如果AOF文件小于auto-aof-rewrite-min-size规定的值,则不会触发重写操作,这避免了在AOF文件不是很大的时候多次触发重写。
当重启Redis进行AOF加载时,可能会发现AOF文件尾部不完整。这种情况只会发生在系统崩溃之后,尤其是使用了ext4文件系统且没有设置data=ordered的情况下。当aof-load-truncated被设置为yes时,Redis发现了问题之后会从AOF文件中尽可能地加载更多的数据,然后在log文件里记录这次错误。设置为no时,服务器会拒绝启动,此时用户可以使用redis-check-aof工具修复损坏的AOF文件。
dir配置AOF文件保存的路径。RDB产生的文件也会被保存到这个路径下面。
通过BGREWRITEAOF命令手动调用AOF重写
用户可以通过执行BGREWRITEAOF命令触发Redis重写AOF文件。为了防止对磁盘进行大量的I/O操作,BGSAVE和BGREWRITEAOF不会同时执行。所以当BGSAVE正在执行的时候用户调用了BGREWRITEAOF,服务器会暂缓执行BGREWRITEAOF,进入预定状态。等到BGSAVE执行完毕之后才会开始执行BGREWRITEAOF。
可以使用INFO命令查看BGREWRITEAOF是否被预定。
其他要注意的地方
AOF和RDB可以同时存在。如果同时存在,Redis服务器启动的时候会优先加载AOF中的数据,因为AOF保存的数据一般来说都比RDB更完整。
Redis对AOF做了一些优化。以下内容摘自NoSQLFan的一篇博客解密Redis持久化。
可以看到,写操作都生成了一条相应的命令作为日志。其中值得注意的是最后一个del命令,它并没有被记录在AOF日志中,这是因为Redis判断出这个命令不会对当前数据集做出修改。所以不需要记录这个无用的写命令。另外AOF日志也不是完全按客户端的请求来生成日志的,比如命令INCRBYFLOAT在记AOF日志时就被记成一条SET记录,因为浮点数操作可能在不同的系统上会不同,所以为了避免同一份日志在不同的系统上生成不同的数据集,所以这里只将操作后的结果通过SET来记录。
总结
AOF为了解决一些RDB无法解决的问题而生,使用AOF可以将数据的损失降到最低。但是AOF也有其局限性(比RDB更占用存储空间、加载速度慢等)。对于那些对数据损失非常敏感的应用程序,AOF是一种非常好的持久化策略,而对于那些对数据损失不敏感的应用程序,AOF就显得可有可无了。总之,开发者应该根据实际情况选择持久化策略,合理运用AOF和RDB的特点,并且将持久化得到的文件备份到其他安全的地方,才能使它们发挥最大的作用。
关于Redis的另一种持久化策略RDB,请读者查看博主的另一篇博客Redis持久化之RDB快照。
参考资料:
解密Redis持久化
Redis命令参考
《Redis实战》(Redis IN ACTION) [美] Josiah L. Carlson
上一篇: ES 6(持续更新)