Redis数据持久化
2015-01-06 架构师之旅
总的来说有两种持久化方案:RDB和AOF
RDB方式按照一定的时间间隔对数据集创建基于时间点的快照。
AOF方式记录Server收到的写操作到日志文件,在Server重启时通过回放这些写操作来重建数据集。该方式类似于MySQL中基于语句格式的binlog。当日志变大时Redis可在后台重写日志。
若仅期望数据在Server运行期间存在则可禁用两种持久化方案。在同一Redis实例中同时开启AOF和RDB方式的数据持久化方案也是可以的。该情况下Redis重启时AOF文件将用于重建原始数据集,因为叫RDB方式而言,AOF方式能最大限度的保证数据完整性。
两钟方案各自的优缺点
RDB优点
RDB是Redis数据集的基于时间点的紧凑的副本,非常适合于备份场景。比如每个小时对RDB文件做一次小的归档,每天对RDB文件做一次大的归档,每月对RDB文件做一次更大的归档。这样可以在必要的时刻选择不同的备份版本进行数据恢复。
由于是一个紧凑的文件,易于传输到远程数据中心或Amazon S3,因此RDB非常适合于灾难恢复。
RDB方式的开销较低,在该种方式下Redis父进程所要做的仅是开辟一个子进程来做剩下的事情。
与AOF相比RDB在数据集较大时能够以更快的速度恢复。
RDB缺点
若需在Redis停止工作时(例如意外断电)尽可能保证数据不丢失,那么RDB不是最好的方案。例如,通常会每隔5分钟或者更长的时间来创建一次快照,如若Redis没有被正确的关闭就可能丢失最近几分钟的数据。
RDB方式需经常调用fork()函数以开辟子进程来实现持久化。在数据集较大、CPU性能不够强悍时fork()调用可能很耗时从而会导致Redis在几毫秒甚至一秒中的时间内不能服务clients。AOF也需要调用fork()但却可以在不影响数据持久性的条件下调整重写logs的频率。
AOF优点
使用AOF方式时Redis持久化更可靠:有三种不同的fsync策略供选择:no fsync at all、fsync every second、 fsync at every query。默认为fsync every second此时的写性能仍然很好,且最坏的情况下可能丢失一秒钟的写操作。
AOF日志是append only方式产生的日志,因此不存在随机访问问题以及意外断电时造成的损毁问题。即使出于某种原因(如磁盘满)日志以一个写了一半的命令结尾,仍可以使用redis-check-aof工具快速进行修复。
当AOF日志逐渐变大后,Redis可在后台自动的重写AOF日志。当Redis在继续追加旧的AOF日志文件时重写日志是完全安全的。Redis利用可以重建当前数据集的最少的命令产生一个全新的日志文件,一旦新的日志文件创建完成Redis开始向新的日志文件追加日志。
AOF日志的格式易于理解易于解析。这在某些场景非常有用。比如,不下心使用FLUSHALL命令清空了所有的数据,同时AOF日志没有发生重写操作,那么就可以简单的通过停止Redis Server移除日志中的最后一条FLUSHALL命令重启Redis Server来恢复数据。
AOF缺点
同样的数据集AOF文件要比RDB文件大很多。
根据使用的fsync方式不同AOF可能比RDB慢很多。在使用no fsync at all时AOF的性能基本与RDB持平,在使用fsync every second时性能有所下降但仍然较高,在使用 fsync at every query时性能较低。然而RDB方式却能在高负载的情况下保证延迟尽可能小。
一些特定的命令可能存在bug从而导致重载AOF日志时不能重建出完全一样的数据集。这样的bugs非常非常罕见,已经通过测试套件做了充分的测试。这种类型的bugs对于RDB来说几乎是不可能的。说的更清晰一点:Redis AOF增量的更新既存的状态而RDB快照每次都重新创建,从概念上讲RDB方式更加健壮。然而,需要注意两点:每次AOF日志被Redis重写的时候日志由包含数据集的实际数据重新生成,与追加AOF文件的方式相比该方式能有效减少bugs出现的概率;现实的应用场景中还未收到过任何用户关于AOF损毁的报告。
如何选择持久化方式?
取决于具体的应用场景,通常,两种方式可同时使用。若比较关心数据但仍能忍受几分钟的数据丢失,那么可以简单的使用RDB方式。有许多用户只使用AOF方式,不建议这种做法,一方面以一定时间间隔创建RDB快照是创建数据备份并快速恢复数据的极好的办法,一方面可以避免AOF方式可能存在的bugs。出于上述原因,将来可能将AOF和RDB方式合二为一。
RDB持久化设置
默认情况下Redis在磁盘上创建二进制格式的命名为dump.rdb的数据快照。可以通过配置文件配置每隔N秒且数据集上至少有M个变化时创建快照、是否对数据进行压缩、快照名称、存放快照的工作目录。redis 2.4.10的默认配置如下:
#900秒后且至少1个key发生变化时创建快照
save 900 1
#300秒后且至少10个key发生变化时创建快照
save 300 10
#60秒后且至少10000个key发生变化时创建快照
save 60 10000
#可通过注释所有save开头的行来禁用RDB持久化
#创建快照时对数据进行压缩
rdbcompression yes
#快照名称
dbfilename dump.rdb
#存放快照的目录(AOF文件也会被存放在此目录)
dir /var/lib/redis/
关于配置参数的详细信息可参阅redis.conf中的说明。
除了通过配置文件进行设置外也可以通过手工执行命令来创建快照
SAVE命令执行一个同步操作,以RDB文件的方式保存实例中所有数据的快照。一般不在生产环境直接使用SAVE 命令,因为会阻塞所有的客户端的请求,可以使用BGSAVE命令代替。BGSAVE后台创建数据快照。命名执行结果的状态码会立即返回。Redis开辟一个子进程,父进程继续相应客户端请求,子进程保存DB到磁盘后退出。客户端可通过执行LASTSAVE命令检查操作是否成功。
创建RDB快照的工作流程
Redis需dump数据集到磁盘时会执行下列过程:
Redis forks一个子进程;
子进程写数据集到临时的RDB文件;
子进程写完新的RDB文件后替换旧的RDB文件。
该方式使Redis可以利用copy-on-write机制的好处。
Copyright © 启程