您的位置:首页 > 数据库 > Redis

Redis数据持久化

2016-04-19 22:03 281 查看
总的来说有两种持久化方案: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的默认配置如下:

[plain] view
plain copy







#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机制的好处。

AOF持久化设置

利用快照的持久化方式不是非常可靠,当运行Redis的计算机停止工作、意外掉电、意外杀掉了Redis进程那么最近写入Redis的数据将会丢。对于某些应用这或许不成问题,但对于持久化要求非常高的应用场景快照方式不是理想的选择。AOF文件是一个替代方案,用以最大限度的持久化数据。同样,可以通过配置文件来开闭AOF:

[plain] view
plain copy







#关闭AOF

appendonly no

#打开AOF

appendonly yes

当设置appendonly为yes后,每次Redis接收到的改变数据集的命令都会被追加到AOF文件。重启Redis后会重放AOF文件来重建数据。

还可以通过配置文件配置AOF文件名、调用fsync的频率、调用fsync的行为、重写AOF的条件。redis 2.4.10的默认配置如下:

[plain] view
plain copy







#默认AOF文件名

appendfilename appendonly.aof

#每秒调用一次fsync刷新数据到磁盘

appendfsync everysec

#当进程中BGSAVE或BGREWRITEAOF命令正在执行时不阻止主进程中的fsync()调用(默认为no,当存在延迟问题时需调整为yes)

no-appendfsync-on-rewrite no

#当AOF增长率为100%且达到了64mb时开始自动重写AOF

auto-aof-rewrite-percentage 100

auto-aof-rewrite-min-size 64mb

各参数含义可参阅redis.conf中详细说明。

几点说明

日志重写

随着Redis接收到的命令的增加AOF文件会变得越来越大。Redis支持日志重写特性,可以在不影响响应客户端的前提下在后台重构AOF文件。当在Redis中执行BGREWRITEAOF后Redis将使用构建数据集所需的最少的命令来重构日志文件。Redis2.2中需要经常手动运行BGREWRITEAOF,Redis2.2开始支持自动触发日志重写。

日志重写同样使用copy-on-write机制,流程大致如下:

Redis开辟一个子进程;

子进程在临时文件中写新的AOF文件;

父进程将所有新的更改缓存在memory中(同时新更改被写入旧的AOF,这样即使重写操作失败了也是安全的);

在子进程重写好临时AOF后父进程收到一个信号并追加memory中缓冲的更改到子进程产生的临时文件的末尾;

Redis进行文件重命名用新的文件替换旧的文件并开始追加新的数据到新文件。

fsync调用模式

该模式决定了Redis刷新数据到磁盘的频率,有三个可选项:

no fsync at all 全由操作系统决定刷数据的时机。最快但最不安全。

fsync every second 每秒一次刷新。足够快,最多可丢失一秒的数据。

fsync at every query 每次记录一条新的命令到AOF便刷一次数据到磁盘。最慢但最安全。

默认策略(也是默认策略)为fsync every second

AOF损坏时的对策

若在写AOF文件时Server崩溃则可能导致AOF文件损坏而不能被Redis载入。可通过如下步骤修复:

创建一个AOF文件的备份;

使用redis-check-aof工具修复原始的AOF文件;

$ redis-check-aof --fix

使用diff -u 检查备份文件和修复后文件的异同(可选步骤);

使用修复后的AOF文件重启Redis。

如何由RDB持久化转换到AOF持久化?

Redis >=2.2时

创建最近的RDB文件的备份;

将备份保存在安全的位置;

发起如下命令;

$redis-cli config set appendonly yes

$redis-cli config set save ""(可选,若不执行RDB和AOF方式将并存)

确认数据库包含相同的keys;

确认write操作被正确追加到了AOF文件。

注意事项:记得修改redis.conf中对应的配置以免Redis Server重启后通过命令进行的配置更新丢失而重新使用旧的配置文件中配置。

Redis2.0时

创建最近的RDB文件的备份;

将备份存放在安全的位置;

停止数据库上的所有写操作;

发起 redis-cli bgrewriteaof命令创建AOF文件;

当AOF文件生成后停止Redis Server;

编辑redis.conf开启AOF持久化;

重启Redis Server;

确认数据库包含相同的keys;

确认write操作被正确追加到了AOF文件。

AOF与RDB之间的相互影响

Redis2.4以上的版本会确保在RDB快照创建时不触发AOF重写或者在AOF重写时不允许BGSAVE操作,以避免Redis后台进程同时做繁重的磁盘I/O操作。

当创建RDB快照时对于用户使用BGREWRITEAOF明确发起的日志重写操作server会立刻回应一个ok状态码告知用户操作将回被执行,当且仅当快照创建完成后重写操作开始被执行。

在同时使用了AOF和RDB方式的情况下,Redis重启后会优先使用AOF文件来重构原始数据集。

备份Redis 数据

务必做好数据备份以防意外丢失。Redis是备份友好的,可在数据库运行时拷贝RDB文件。建议的备份方案:

创建一个cron作业在一个目录中每小时创建一次RDB快照在另一目录中每天创建一次RDB快照;

cron作业每次运行的时候使用find命令确保过时的RDB快照文件被清理掉(可以通过在快照命中包含数据和时间信息来进行标记);

确保将RDB快照转移到外部的数据中心或者至少是运行Redis实例的物理机之外的机器(至少每天一次)。

灾难恢复

在Redis中灾难恢复和数据备份基本上是同样的过程。可考虑将备份分布到不同的远程数据中心以最大限度的避免数据丢失。几种低成本的灾难恢复计划:

Amazon S3或其它类似服务是很好的选择。可将每天会每小时的RDB快照以加密的方式(可使用gpg -c加密)传输到S3。确保将密码存储在不同的安全的地方。建议使用不同的存储服务以提高数据安全性。

使用SCP命令将快照传输到远程服务器。最简单和安全的方式:获取一个小的远程VPS,在其上安装ssh,生成无密码的ssh client key添加到VPS的authorized_keys文件,此后便可使用SCP传输备份到VPS了。建议搞两个不同的VPS以提高安全性。

需要注意的是,文件传输完成后一定要校验文件的完整性正确性。可通过MD5或SHA1进行验证。另外需要搭建一套告警系统,当备份传输发生问题时能及时的告知。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: