Redis从入门到精通(四、Redis的持久化和数据备份与恢复)

Redis提供了两种持久化的选项,一种是快照文件(snapshotting,RDB),它会基于某个时间点将数据全部写入硬盘中(默认为dump.rdb)。另一种是只追加文件(append-only,AOF),它会在执行写入命令时将命令写入到硬盘中。

Redis持久化数据最主要是为了数据备份,故障恢复,也有一些经过耗时较长的计算结果存在Redis中,如果这些数据存在硬盘中,即使服务器重启了之后,这些数据还是存在的,不用再去耗时计算了。

这两种方式可以单独使用,也可以结合起来使用。最重要的还是要理解RDB和AOF的优劣势,结合自己的应用做一个权衡。

RDB (SNAPSHOTTING)

RDB 配置项

save 900 1
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir ./

上面6项配置中,前5项均是RDB的配置,最后一个是RDBAOF 公用的配置

  • dir ./,指定 RDBAOF 文件的路径
  • save 900 1 , 多久执行一次快照操作, 900秒内有1次写入则执行快照操作
  • stop-writes-on-bgsave-error , 创建快照失败后是否依然写命令,默认为yes
  • rdbcompression , 是否对快照文件进行压缩,默认为 yes
  • rdbchecksum , rdb文件是否启用CRC64文件数据完整性检查,5.0版本之后的属性,默认为 yes,开启后在 saveload 时将耗费 10%的性能,可以关闭此配置来提高性能
  • dbfilename , rdb文件名,默认为 dump.rdb

RDB 详解

Redis 通过创建快照的方式,获得内存中某个时间点的数据副本。Redis重启时可以从 RDB 文件上恢复数据。我们也可以把 RDB 文件备份在别的服务器上。

根据上述的几个配置项,快照被写入 dir 目录下的 dbfilename 文件中。如果在新的快照文件创建完成之前,Redis服务器发生了宕机,那这期间的数据将丢失。

Redis中有两个命令可以创建快照文件, SAVEBGSAVE

  • 执行 SAVE 命令后,服务器将不会再相应任何命令,直到快照文件完成。
  • 执行 BGSAVE 命令后,Redis父进程会调用 fork 来创建一个子进程,由子进程去负责快照文件的写入,父进程则继续处理客户端的命令请求。
  1. 客户端可以直接向服务器发送 SAVE 或者 BGSAVE
  2. 如果设置了 save 配置项,达到配置项的要求时,Redis会自动执行 BGSAVE 命令。该配置项可以设置多组,如果设置了多组,只要达到其中一组的要求,就会执行BGSAVE
  3. Redis通过SHUTDOWN 指令,或者接收到标准 TERM 信号时,会执行 SAVE 命令,阻塞所有客户端,直到 SAVE 命令执行完成后,关闭服务器
  4. Redis配置了复制集之后,从服务器向主服务器发来 SYNC 命令,主服务器会执行 BGSAVE 命令,然后将快照文件发给从服务器

需要注意的是, 执行 BGSAVE 命令可能会造成服务器暂停几毫秒或者几秒,具体时长要根据数据量的大小以及服务器的配置来看。在数据量特别大,服务器内存吃紧的情况下,可能会造成长时间的停顿,甚至宕机。通常情况下, BGSAVE 是要比 SAVE 好一些,因为不会影响客户端的请求,不过在数据量巨大的情况下, BGSAVE 可能会比 SAVE 指令耗时更长。所以还是要结合具体的数据情况来选择。如果可以接受数据丢失5分钟,15分钟,1小时甚至更长时间的数据的话,甚至可以关闭自动保存,由客户端决定什么时候来执行快照副本的创建。

RDB 优点

  • 冷备份,例如:可以设置每个小时归档数据集,并备份至其他服务器,发生灾难时可以选择恢复数据集的不同副本。
  • 对 Redis 的读写影响小,最大限度的提高了性能。父进程会fork一个子进程区做数据集的归档,不会影响父进程的工作。
  • 在恢复数据集时,RDB比AOF更加高效

RDB 缺点

  • 在发生灾难的时候,RDB会比AOF丢失的数据多。可以通过设置来更改保存点,一般设置为5分钟。
  • RDB 每次在fork子线程来执行RDB快照文件时,如果数据文件特别大且CPU性能不佳,可能造成服务暂停几毫秒或者几秒。

AOF (append-only)

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
aof-use-rdb-preamble yes
  • appendonly,是否开启 AOF,默认为 no
  • appendfilename, AOF 文件名
  • appendfsync ① ,多久才将写入的内容同步到硬盘上,有 always,everysec(默认),no 三种。下面对比了三种方式的性能
  • no-appendfsync-on-rewrite ,在重写时是否执行fsync操作,默认为 no
  • auto-aof-rewrite-percentage ②, 当文件达到上一个文件的多少百分比时自动重写
  • auto-aof-rewrite-min-size ②,自动重写的最小文件体积
  • aof-load-truncated ③,AOF文件被截断时是否启动,默认为 yes
  • aof-use-rdb-preamble ④,是否支持AOF和RDB混合使用,默认为 yes

(1) 关于 appendfsync 的说明

选项 同步频率
always 每次执行写入操作都执行fsync,这将非常影响性能,严重降低Redis的吞吐
everysec 每隔1s执行一次 fsync,显示的将多个写入命令同步到硬盘,性能非常好,如果丢失数据也只是丢失1s内的数据
no 不执行 fsync ,交给操作系统去处理。一般Linux是每隔30s刷新一次数据到磁盘上,取决于内核的精准调整

(2) 关于 rewrite

前面提到,AOF是将每条写入命令都同步到硬盘,包括删除key的指令,一直这么下去,AOF文件将会变的非常庞大,甚至占用所有硬盘空间。

rewrite 就是解决这个问题的,它对应的命令是 BGREWRITEAOF , 这个命令和 BGSAVE 非常相似,都是由Redis父进程fork的子进程去执行操作,所以它和 BGSAVE 有相同的缺点。
BGREWRITEAOF 会通过移除AOF中冗余命令的方式来重写AOF文件,重写之后体积就会变小很多。

auto-aof-rewrite-percentageauto-aof-rewrite-min-size 这两项配置是配置自动重写AOF文件的触发条件,只有在设置了 appendonly yes 的情况下,也就是开启了AOF持久化机制才会生效。
举个例子,auto-aof-rewrite-percentage 100, auto-aof-rewrite-min-size 64mb 表示,当AOF大于 64mb 并且比上一次重写之后的体积大了100% 才会执行BGREWRITEAOF。可以通过修改这两项参数来控制AOF重写的频率。

(3) 关于 aof-load-truncated

在写入AOF文件的过程中,可能会由于各种原因(停电,磁盘空间占满,服务器故障导致Redis宕机)导致AOF写入命令被截断,如果该配置项设置为 yes , Redis将会在重启时,清除被截断的命令之后的所有命令(通常情况下后面也没有命令了),然后正常重启。如果不想这样,可以将此项设置为 no ,Redis将会在重启时抛出错误并退出。需要注意的是:最新版本中即使设置了 no , Redis也会将被截断的命令之后所有命令删除,以保证下次重新启动时能够正常启动,老版本中则不会,需要使用 redis-check-aof 工具来修复,具体命令是redis-check-aof --fix

以下是aof-load-truncated yes的情况下,Redis重启时发现了AOF被截断,打出的日志

* Reading RDB preamble from AOF file...
* Reading the remaining AOF tail...
# !!! Warning: short read while loading the AOF file !!!
# !!! Truncating the AOF at offset 439 !!!
# AOF loaded anyway because aof-load-truncated is enabled

(4) 关于 aof-use-rdb-preamble

Redis4.0以后,支持AOF和RDB混合使用,可以通过此项进行配置是否开启。

AOF 详解

AOF机制对每条写入命令作为日志,以append-only的模式写入一个日志文件中,在redis重启的时候,可以通过回放AOF日志中的写入指令来重新构建整个数据集。
Redis并不会将数据直接写入硬盘中,而是会先将数据写进linux os cache,然后在通过配置的appendfsync 设置的时间来执行fsync操作,强行将数据刷入磁盘文件。
AOF是存放每条的写命令,所以会不断扩大,当大到一定程度,AOF做rewrite操作,就会基于当时redis内存中的数据,来重新构造一个更小的AOF文件,然后将旧的文件删掉。

AOF 优点

  • AOF可以更好的保护数据不丢失,一般AOF每隔一秒,通过后台线程执行一次fsync,最多丢失1s的数据。可以通过设置改为每次写入数据时都执行fsync,不过这非常影响性能。
  • AOF日志仅仅时附加日志,如果因为某些原因导致只写入一般,也可以通过redis-check-aof 轻松修复。
  • AOF日志文件过大时,会在后台执行rewrite操作,不会影响客户端的读写
  • AOF日志文件可能性好,因为记录的时一条一条的指令。

AOF 缺点

  • AOF日志通常比RDB数据快照文件更大
  • 做数据恢复的时候可能会比RDB慢
  • 做定期的冷备没有RDB方便

RDB和AOF文件损坏了

Redis为我们提供了工具,redis-check-rdbredis-check-aof

具体使用方法如下:

[root@iZnom30el3gvhxZ ~]# redis-check-aof
Usage: redis-check-aof [--fix] <file.aof>
[root@iZnom30el3gvhxZ ~]# redis-check-rdb
Usage: redis-check-rdb <rdb-file-name>

下面是官方文档中对于AOF文件损坏的一些说明,我摘了过来:

If the AOF file is not just truncated, but corrupted with invalid byte sequences in the middle, things are more complex. Redis will complain at startup and will abort:

* Reading the remaining AOF tail...
# Bad file format reading the append only file: make a backup of your AOF file, then use ./redis-check-aof --fix <filename>

The best thing to do is to run the redis-check-aof utility, initially without the --fix option, then understand the problem, jump at the given offset in the file, and see if it is possible to manually repair the file: the AOF uses the same format of the Redis protocol and is quite simple to fix manually. Otherwise it is possible to let the utility fix the file for us, but in that case all the AOF portion from the invalid part to the end of the file may be discareded, leading to a massive amount of data lost if the corruption happen to be in the initial part of the file.

How it works

Log rewriting uses the same copy-on-write trick already in use for snapshotting. This is how it works:

  • Redis forks, so now we have a child and a parent process.
  • The child starts writing the new AOF in a temporary file.
  • The parent accumulates all the new changes in an in-memory buffer (but at the same time it writes the new changes in the old append-only file, so if the rewriting fails, we are safe).
  • When the child is done rewriting the file, the parent gets a signal, and appends the in-memory buffer at the end of the file generated by the child.
  • Profit! Now Redis atomically renames the old file into the new one, and starts appending new data into the new file.

How I can switch to AOF, if I'm currently using dump.rdb snapshots?

There is a different procedure to do this in Redis 2.0 and Redis 2.2, as you can guess it's simpler in Redis 2.2 and does not require a restart at all.

Redis >= 2.2

  • Make a backup of your latest dump.rdb file.
  • Transfer this backup into a safe place.
  • Issue the following two commands:
  • redis-cli config set appendonly yes
  • redis-cli config set save ""
  • Make sure that your database contains the same number of keys it contained.
  • Make sure that writes are appended to the append only file correctly.

The first CONFIG command enables the Append Only File. In order to do so Redis will block to generate the initial dump, then will open the file for writing, and will start appending all the next write queries.

The second CONFIG command is used to turn off snapshotting persistence. This is optional, if you wish you can take both the persistence methods enabled.

IMPORTANT: remember to edit your redis.conf to turn on the AOF, otherwise when you restart the server the configuration changes will be lost and the server will start again with the old configuration.

Redis 2.0

  • Make a backup of your latest dump.rdb file.
  • Transfer this backup into a safe place.
  • Stop all the writes against the database!
  • Issue a redis-cli bgrewriteaof. This will create the append only file.
  • Stop the server when Redis finished generating the AOF dump.
  • Edit redis.conf end enable append only file persistence.
  • Restart the server.
  • Make sure that your database contains the same number of keys it contained.
  • Make sure that writes are appended to the append only file correctly.

RDB和AOF如何选择?

通过以上内容,应该已经对RDB和AOF两种方式的优缺点有了大概的了解,具体如何选择,还需根据自己的业务情况来选择,这里给出的意见是两种一起用,条件允许的话,将持久化的文件时常备份到多台不同的服务器上。

Redis4.0以后,支持AOF和RDB混合使用,在 redis.conf 中通过 aof-use-rdb-preamble yes 设置。

其他

以下是Redis官方文档中关于 数据备份灾难恢复 的说明,我做了一下翻译,官方给出的方案已经很完善了,可以参考以下,结合自己的实际情况实施

数据备份

在开始本节之前,确保读了以下句子:对你的数据库做备份。磁盘损坏,云实例消失等等:没有备份意味着将数据丢失到 /dev/null

Redis对于数据备份非常友好,因为你可以在数据库运行时拷贝RDB文件: RDB文件一旦生成就不会改变,它在生成时使用一个临时的名字,当新的快照文件完成之后会以原子的方式 rename 确保替换掉旧的快照文件。

这意味着当数据库正在运行时拷贝RDB文件是安全的。下面是我们的建议:

  • 在服务器中创建一个 cron 作业,在一个文件夹中每隔一个小时创建一次快照的副本,在另一个文件夹中每隔一天创建一次快照的副本。
  • 每次运行 cron 作业的脚本时,确保调用一次 find 命令来确保删除太旧的快照副本: 例如,你可以保留最近48小时的每小时快照副本和一两个月内的每日快照副本。确保使用数据和时间信息命名快照副本。
  • 每天至少一次把这些RDB快照备份到 数据中心之外 或者 至少是运行着Redis实例的物理机之外。

如果Redis只开启了AOF的持久化模式,也仍然可以创建AOF文件的备份。该文件可能缺少最后部分,但是Redis仍然可以加载它(参考AOF文件被截断相关内容)。

灾难恢复

Redis的灾难恢复和备份基本相同,而且可以传输到许多不同的数据中心。以这种方式保护数据,即使在正运行着Redis的实例的主数据中心发生了灾难性事件,这些备份的数据也很安全。

由于许多Redis用户正处于起始阶段,可能没有足够的资金去执行上述方案。我们将介绍最有趣的灾难恢复方案,这些技术成本不会很高。

  • 亚马逊S3和其他云是实现你的灾难恢复系统的一个好方案。用加密的方式把你的每日和每小时的数据快照传输到S3。你可以用gpg -c(对称加密)加密你的数据。保证把你的密码保存在其他安全的地方(比如给你的组织中最重要的人一个副本)。推荐你使用多个数据存储服务来提升你的数据安全性。
  • 用SCP(SSH的一部分)将你的快照传到其他远程服务器。这是一个相当简单和安全的方式: 在离你很远的地方获取一个VPS,在那里安装SSH,并生成一个没有密码的ssh客户端,然后把它添加到VPS的 authorized_keys 文件中。你已经准备好了以自动的方式传输这些备份文件。至少从两个不同的VPS提供商获取VPS,以保证最好的结果。

最重要的是理解,如果你没有以正确的方式去实现上述方案。至少绝对确保在传输完成之后检查文件的大小(它应该要和你复制的文件大小一致),如果你使用VPS的话,还要验证SHA1摘要。

如果备份在传输过程中由于某些原因失败了,你也需要一套独立的警报系统。


更多详细内容参考:

Redis持久化官方文档

Redis实战

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343