玖叶教程网

前端编程开发入门

关于Redis 持久化的问题(redis持久化的几种方式,优缺点是什么,怎么实现的)

引用文章:http://www.redis.cn/topics/persistence.html

Redis官方地址:https://redis.io/topics/persistence

Redis 提供不同级别持久化方案

· RDB 持久化方式能在指定时间周期内对数据进行快照存储

· AOF ( Append-only file )持久化方式记录每次对 Redis 的写操作命令,当 Redis 重启,会重新执行这些命令以恢复原始数据, AOF 命令遵循 Redis 协议追加到文件末尾, Redis 还能对AOF 文件进行后台重写(轮询文件) , 使得 AOF 文件的体积不至于过大 。

·如果你只希望你的数据在服务器运行的时候存在 , 你也可以不使用任何持久化方式 .

·也 可以同时开启两种持久化方式。当 Redis 重启,会优先载入 AOF 文件来恢复原始数据(一般 AOF 文件保存的数据库要比 RDB 文件保存的数据库完整)

RDB 优点

· RDB 文件十分紧凑( compact ),保存某个时间及该时间以前的数据集,如:每小时保存一下数据,那么 30 天后,如果出问题,可以根据需求恢复不同时间版本的数据集

·非常适合备份,或灾难恢复,在出现问题后,直接传送紧凑的 RDB 单文件进行恢复。

· RDB 在保存 RDB 文件时父进程唯一需要做的就是 fork 出一个子进程 , 接下来的工作全部由子进程来做,父进程不需要再做其他 IO 操作,所以 RDB 持久化方式可以最大化 Redis 的性能

·与 AOF 相比 , 在恢复大的数据集时, RDB 方式会更快一些

RDB 缺点

·若希望 Redis 意外停止工作(如服务器断电)时丢失最少数据,那 AOF 方式更适合,虽然可配置不同的 save 时间点(如每 5 分钟数据集有 100 个写操作时执行持久化),但最后一次持久化后的数据更新无法保存到磁盘

· RDB 需要经常 fork 子进程来保存数据集到硬盘上 , 当数据集比较大的时候 ,fork 的过程是非常耗时的 , 可能会导致 Redis 在一些毫秒级内不能响应客户端的请求 . 如果数据集巨大并且 CPU 性能不是很好的情况下 , 这种情况会持续 1 秒 ,AOF 也需要 fork, 但是你可以调节重写日志文件的频率来提高数据集的耐久度 ( 产品能够无故障的使用较长时间或使用寿命长 )

AOF 优点

· AOF 方式能提高 Redis 数据集的耐久度,可以有多种 fsync 策略:

完全无 fsync;

每秒 fsync;( 默认策略 ) , (fsync 是由后台线程进行处理的 , 主线程会尽力处理客户端请求 ), 一旦出现故障,你最多丢失 1 秒的数据

每次写 fsync;

· AOF 会追加日志到文件,而不需要搜索文件内容,即使由于某些原因 ( 磁盘空间已满,写的过程中宕机等等 ) 未执行完整的写入命令 , 你也也可使用 Redis-check-aof 工具修复这些问题

· Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写(轮询文件):重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合。整个重写操作是绝对安全的,因为Redis 在创建新 AOF 文件时,会继续将命令追加到现有的 AOF 文件里面,即使重写过程中发生停机,现有的 AOF 文件也不会丢失。而一旦新 AOF 文件创建完毕, Redis 就会从旧 AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操作

· AOF 文件按照命令执行顺序保存对数据库执行的所有写入操作,这些写入操作以 Redis 协议格式保存,因此 AOF 文件易读性高,分析方便,同时 AOF 文件导出也很便捷。举个例子,如果你不小心执行了 FLUSHALL 命令, 但只要 AOF 文件未被重写, 那么只要停止服务器,移除 AOF 文件末尾的 FLUSHALL 命令, 并重启 Redis , 就可以将数据集恢复到 FLUSHALL 执行之前的状态

AOF 缺点

·对于相同的数据集来说, AOF 文件的体积通常要大于 RDB 文件的体积(保存的是命令列表,相较于直接保存数据更占用空间)

·根据所使用的 fsync 策略, AOF 的持久化速度可能会慢于 RDB ,尽管如此,每秒 fsync 的性能依然非常高,而关闭 fsync 可以让 AOF 的持久化速度和 RDB 一样快, 即使在高负荷之下也是如此。不过,在写入巨量数据时, RDB 能保证比较低的延迟 (latency)

· bug : In the past we experienced rare bugs in specific commands (BRPOPLPUSH 之类的阻塞命令 ) causing the AOF produced to not reproduce exactly the same dataset on reloading. This bugs are rare and we have tests in the test suite creating random complex datasets automatically and reloading them to check everything is ok, but this kind of bugs are almost impossible with RDB persistence. To make this point more clear: the Redis AOF works incrementally updating an existing state, like MySQL or MongoDB does, while the RDB snapshotting creates everything from scratch again and again, that is conceptually more robust. However - 1) It should be noted that every time the AOF is rewritten by Redis it is recreated from scratch starting from the actual data contained in the data set, making resistance to bugs stronger compared to an always appending AOF file (or one rewritten reading the old AOF instead of reading the data in memory). 2) We never had a single report from users about an AOF corruption that was detected in the real world.

如何选择哪种持久化方式?

若想达到足以媲美 PostgreSQL 的数据安全性,应该同时使用两种持久化功能;

若能承受数分钟内数据丢失,可只使用 RDB 持久化;

很多场景用户都只使用 AOF 持久化,但并不推荐:因为定时生成 RDB 快照 (snapshot), 非常便于进行数据备份,且 RDB 恢复数据集速度比 AOF 快,此外,使用 RDB 还可以避免之前提到的 AOF 程序的 bug ;

因为以上提到的种种原因, 未来官方可能会将 AOF 和 RDB 整合成单个持久化模型

快照

默认地, Redis 将数据库快照保存在名字为 dump.rdb 的二进制文件中;

可对 Redis 进行设置,让它在 ” N 秒内至少有 M 个改动 ” 这一条件被满足时,自动保存数据集一次 ( 也可通过调用 SAVE 或者 BGSAVE ,手动让 Redis 进行数据集保存操作 )

以下是实例配置:

save 900 1 # 900 秒内如果键值修改过 1 次就快照

save 300 10 # 300 秒内如果键值修改过 10 次就快照

save 60 10000 # 60 秒内键值修改过 10000 次就快照

stop-writes-on-bgsave-error yes # 后台备份出错时,是否禁止新的写入操作?如果不禁止容易造成数据不一致

rdbcompression yes # 导出的 rdb 文件是否压缩

rdbchecksum yes # 恢复时导入 rdb 文件是否检验完整性、是否检验版本是否一致

dbfilename dump.rdb # 导出来得 rdb 文件名

dir /var/lib/redis # rdb 的存放路径

此为快照 (snapshotting) 。

工作方式:

当 Redis 需要保存 dump.rdb 文件时,服务器执行以下操作:

1 、 Redis 调用 forks ,同时拥有父进程和子进程;

2 、子进程将数据集写入到一个临时 RDB 文件中;

3 、当子进程完成对新 RDB 文件的写入时, Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件 ( 写时复制 )

AOF append-only file

使用 RDB 持久化方式在 Redis 服务故障时,服务器将丢失最近写入,且仍未保存到快照中的数据

1.1 版本开始, Redis 增加了一种完全耐久的 AOF 持久化方式,打开 AOF 功能:

appendonly no # 是否开启 aof 功能

appendfilename "appendonly.aof" # 文件名

appendfsync always # 只要一修改就同步至缓冲区,并同步至磁盘

appendfsync everysec # 每秒将数据同步至缓冲区,并同步至磁盘

appendfsync no # redis 不设定同步策略,由内核设定的参数决定是否同步

no-appendfsync-on-rewrite no # appendfsync 设定为 always everysec 的话,还要不要同步磁盘

auto-aof-rewrite-percentage 100 # 每隔多久重构 aof 文件,单位秒

auto-aof-rewrite-min-size 64mb # aof 文件最小为多少时重构一次 aof 文件。搭配上一条使用

aof-load-truncated yes # 崩溃修复后自动进行全备

日志重写

由于 AOF 工作原理是不断将写入命令追加到文件末尾,因此随着命令不断增加, AOF 文件体积也会变得越来越大。如,将一个计数器增量 100 次,保存命令记录就需要使用 100 条记录,然而实际上,只是用一条 SET 命令就完全能保存计数器当前的值。

对此, Redis 新增特性:在不阻塞或中断客户端的前提下,对 AOF 进行重建 (rebuild) 。执行BGREWRITEAOF 命令, Redis 将生成新的 AOF 文件,此文件包含重建当前数据集所需的最少命令 ( 如此恢复时能减少耗时 ) 。 Redis 2.2 版本需要手动执行 BGREWRITEAOF 命令; Redis 2.4 后则可自动触发 AOF 重写

AOF 持久化 fsync 频率

Redis fsync (或持久化)数据方式:

·有新写入就追加命令到 AOF 文件就 fsync 一次:非常慢,但异常安全

·每秒 fsync 一次:足够快 ( RDB 持久化差不多 ) ,且故障时只会丢失一秒的数据

·从不 fsync :将数据交给操作系统处理,更快,但数据丢失风险高

推荐每秒 fsync 一次 ( 也是默认策略 ) ,此种策略能兼备速度和安全性。

AOF 文件损坏处理方法

程序正在写入 AOF 文件时,服务器宕机可能会造成 AOF 文件出错( corrupt ),那么 Redis重启时会拒绝载入 AOF 文件,从而确保数据一致性。

此时 AOF 文件修复方法:

1、 为现有 AOF 文件创建备份

2、 使用 ” redis-check-aof 修复 AOF 文件: /usr/local/redis/src/redis-check-aof [--fix] <file.aof>

3、 ( 可选 ) 使用 diff -u 对比修复后的 AOF 文件和原始 AOF 文件的备份,查看两个文件之间的不同之处

4、 重启 Redis 服务,等待服务器载入修复后的 AOF 文件,并进行数据恢复

AOF 工作原理:

AOF 重写和 RDB 创建快照一样,都利用写时复制机制。

1、 Redis 执行 fork() ,此时 Redis 存在父进程和子进程

2、 子进程开始将新 AOF 文件的内容写入到临时文件

3、 对于新执行的写入命令,父进程将之累计到内存中,一边将这些改动追加到现有 AOF 文件的末尾 ( 如此,即使重写中途宕机,现有 AOF 文件还是安全的 )

4、 当子进程完成重写工作,会发送一个信号给父进程,父进程收到信号后,将内存中所有数据追加到新 AOF 文件末尾

5、 此时, Redis 原子地用新文件替换旧文件,此后所有命令都直接追加到新 AOF 文件末尾

RDB 方式切换为 AOF 方式

Redis2.2 版本后,支持热切换:

1、 为最新的 dump.rdb 创建备份,放至安全位置

2、 执行命令:

redis-cli config set appendonly yes# 开启 AOF 功能, Redis 会阻塞直到初始 AOF 文件创建完成为止, 之后 Redis 会继续处理命令请求, 并开始将写入命令追加到 AOF 文件末尾

redis-cli config set save “” # 关闭 RDB 功能。 这一步是可选的, 如果你愿意的话, 也可以同时使用 RDB AOF 这两种持久化功能。

3 redis-cli config rewrite# 重写此配置到 redis.conf 配置文件

4 、确保命令被正确地追加 AOF 文件末尾

AOF RDB 间的相互作用

自 Redis2.4 版本起, BGSAVE 执行的过程中,不可以执行 BGREWRITEAOF 。 反过来说,在 BGREWRITEAOF 执行的过程中, 也不可以执行 BGSAVE 。这可以防止两个 Redis 后台进程同时对磁盘进行大量的 I/O 操作 。

如果 BGSAVE 正在执行, 并且用户显示地调用 BGREWRITEAOF 命令,那么服务器将向用户回复一个 OK 状态,并告知用户, BGREWRITEAOF 已经被预定执行:一旦 BGSAVE 执行完毕, BGREWRITEAOF 就会正式开始。 当 Redis 启动时, 如果 RDB 持久化和 AOF 持久化都被打开了, 那么程序会优先使用 AOF 文件来恢复数据集,因为 AOF 文件所保存的数据通常是最完整的

备份 redis 持久化后的数据

牢记一句话: 确保你的数据有完整的备份

磁盘故障,节点失效,此类问题都可能让数据出现问题,没有备份计划是非常危险的,

Redis 备份数据文件十分方便,由于 RDB 文件一旦被创建就不会进行任何修改,因此可以无阻塞,无中断的热备份。当服务器要创建一个新的 RDB 文件时,现将文件内容保存在一个临时文件里面,当临时文件写入完毕,程序才会将临时文件替换成原来的 RDB 文件( rename )。

建议使用 crontab 计划任务执行定期备份,如:

·每小时将 RDB 文件备份至一文件夹,然后每天将该目录备份至另外的服务器

·确保快照的备份都有相应的日期和时间信息,每次执行定期任务脚本时,使用 find 来删除过期快照,比如保存最近一周内每小时的快照

容灾备份

Redis 容灾备份就是数据备份,且将这些备份复制到多个不同的数据中心,至少是不同的服务器。

要注意的是,应该自文件传送完毕后检查所传送的备份文件体积与原始文件是否相同,也可以比对文件 SHA1 值,来确认文件是否传送完整。

最好,创建一个监控,负责在备份文件或者传送文件出现问题是发出告警。

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言