快照
在默认情况下,Redis将数据集的快照通过一个名为dump.rdb的二进制文件保存在磁盘上。你可以通过修改Redis的配置文件,使它可以在每N秒内至少有M条记录产生变化的时候对数据集进行保存,你也可以通过手动执行 SAVE 或 BGSAVE 命令来实现。
例如,以下配置就可以使得Redis在60秒内至少有1000条数据变化的时候,自动进行数据集从内存至磁盘的转储操作。
save 60 1000
这个策略就被称之为快照技术。
快照工作原理每当Redis需要将数据集转储到磁盘上的时候,会执行以下步骤:
Redis forks进程。我们将会得到一个子进程和父进程。子进程开始将数据写入至一个临时的RDB文件中。当子进程写入操作完毕后,会将新生成的RDB文件替换掉之前使用的那个。Redis的这种实现,得益于Copy-on-write策略。(思门注:关于Copy-on-write技术,可以参考via)
增量文件快照方式并不是非常可靠的。如果你的计算机(意外)停止运行Redis,例如电源线坏了,或者误操作执行了kill -9 你的Redis实例,最新写入Redis的内存数据将会丢失。虽然这样对于某些应用而言并不是什么大问题,但是如果是对可靠性有很高要求的应用,那么在这时侯Redis使用快照未必是一个好的选择。
增量文件才是一个可用的,完全持久的Redis策略。这个特性从1.1版本开始可用。
你可以在配置文件中打开文件追加功能:
appendonly yes
从现在起,每当Redis接收到一条会对数据集产生修改的命令(例如SET),它都会写入到额外的增量文件中。当你重新启动Redis的时候,它将重新加载增量文件,并恢复之前的状态。(思门注:在默认情况下,追加的AOF文件的名是appendonly.aof,当然你可以根据自己需要进行修改)
日志重写正如你所猜想的那样,增量文件特性开启后会随着不停的写入操作导致文件越来越大。举个例子,如果你对一个计数器执行100次递增操作,你可以在结束时通过一个单key从数据集中得到最终结果,但是在增量文件中却会产生100条记录。像这种情况下,有99条记录对于重建状态都是不需要的。
因此Redis支持了一种有趣的特性:允许在不中断服务的情况下,在后端进行增量文件的重建工作。每当你向Redis发出BGREWRITEAOF命令的时候,都会将(在内存中)重建当前数据集所需要的最小命令队列写入到增量文件中。如果你正在使用增量文件特性,你应该时不时的执行一下BGREWRITEAOF命令。
增量文件到底有多可靠?你可以通过配置来修改Redis往磁盘上fsync数据的频率。有下面三种选项供参考:
每当一条新命令写入增量文件时都将执行文件同步。非常非常低效,但是数据很安全。每秒执行一次文件同步。速度足够快,但是你可能会灾难性的丢失1秒内写入的数据。永不同步,只是把数据交给操作系统,这是速度更快,但是相对安全性较低的方式。比较稳妥(也是默认)的方式是每秒同步一次。不但速度很快,也保证了数据安全。始终同步策略在实践中是非常慢的(尽管在Redis2.0中有了一定提升)—— 因为没有办法让fsync操作变得更快了。
当我的增量文件损坏时该怎么办?很可能你的服务器在写入增量文件的时候发生了碰撞(这仍然不应该导致产生差异),在某种程度上可能导致Redis无法加载该文件。当这种情况发生时,你可以通过以下方式来解决问题:
把你的增量文件做一个备份通过使用Redis内置的 redis-check-aof 工具修复原始文件:$ redis-check-aof –fix
可以使用 diff -u 检查对比两个文件之间的差异通过使用修复后的文件,重启服务日志重写工作原理日志重写与快照一样,使用了Copy-on-write技术。下面是工作原理:
Redis forks进程,因此我们又会得到一个子进程和父进程。(思门注:为什么说又?)子进程将在一个临时文件中写入新的增量文件。父进程在内存缓冲区中记录所有新的变化(但是与此同时,父进程会把这些变更写入到旧的增量文件中,这样即使重写失败,我们的数据依旧是安全的)。当子进程完成文件重写操作时,父进程会接收到一个信号,并把内存缓存区的数据追加到由子进程生成的文件中去。搞定!现在Redis将旧文件原子重命名为一个新的文件,并在之后往新文件中进行数据追加。