【Redis学习】Redis持久化

1、RDB

1.1 工作原理

Redis调用fork(),产生一个子进程。
子进程把数据写到一个临时的RDB文件。
当子进程写完新的RDB文件后,把旧的RDB文件替换掉。

1.2 优点

RDB文件是一个很简洁的单文件,它保存了某个时间点的Redis数据,很适合用于做备份。你可以设定一个时间点对RDB文件进行归档,这样就能在需要的时候很轻易的把数据恢复到不同的版本。

基于上面所描述的特性,RDB很适合用于灾备。单文件很方便就能传输到远程的服务器上。

RDB的性能很好,需要进行持久化时,主进程会fork一个子进程出来,然后把持久化的工作交给子进程,自己不会有相关的I/O操作。
比起AOF,在数据量比较大的情况下,RDB的启动速度更快。

1.3 缺点

RDB容易造成数据的丢失。假设每5分钟保存一次快照,如果Redis因为某些原因不能正常工作,那么从上次产生快照到Redis出现问题这段时间的数据就会丢失了。

RDB使用fork()产生子进程进行数据的持久化,如果数据比较大的话可能就会花费点时间,造成Redis停止服务几毫秒。如果数据量很大且CPU性能不是很好的时候,停止服务的时间甚至会到1秒。

1.4 文件路径和名称

默认Redis会把快照文件存储为当前目录下一个名为dump.rdb的文件。要修改文件的存储路径和名称,可以通过修改配置文件redis.conf实现:


# RDB文件名,默认为dump.rdb。
dbfilename dump.rdb

# 文件存放的目录,AOF文件同样存放在此目录下。默认为当前工作目录。
dir ./
1.5 保存点(RDB的启用和禁用)

你可以配置保存点,使Redis如果在每N秒后数据发生了M次改变就保存快照文件。例如下面这个保存点配置表示每60秒,如果数据发生了1000次以上的变动,Redis就会自动保存快照文件:

save 60 1000
保存点可以设置多个,Redis的配置文件就默认设置了3个保存点:

# 格式为:save <seconds> <changes>
# 可以设置多个。
save 900 1 #900秒后至少1个key有变动
save 300 10 #300秒后至少10个key有变动
save 60 10000 #60秒后至少10000个key有变动

如果想禁用快照保存的功能,可以通过注释掉所有”save”配置达到,或者在最后一条”save”配置后添加如下的配置:

save ""
1.6 错误处理

默认情况下,如果Redis在后台生成快照的时候失败,那么就会停止接收数据,目的是让用户能知道数据没有持久化成功。但是如果你有其他的方式可以监控到Redis及其持久化的状态,那么可以把这个功能禁止掉。

stop-writes-on-bgsave-error yes
1.7 数据压缩

默认Redis会采用LZF对数据进行压缩。如果你想节省点CPU的性能,你可以把压缩功能禁用掉,但是数据集就会比没压缩的时候要打。

rdbcompression yes
1.8 数据校验

从版本5的RDB的开始,一个CRC64的校验码会放在文件的末尾。这样更能保证文件的完整性,但是在保存或者加载文件时会损失一定的性能(大概10%)。如果想追求更高的性能,可以把它禁用掉,这样文件在写入校验码时会用0替代,加载的时候看到0就会直接跳过校验。

rdbchecksum yes
1.9 RDB 快照

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

你可以对 Redis 进行设置, 让它在“ N 秒内数据集至少有 M 个改动”这一条件被满足时, 自动保存一次数据集。

Redis提供了两个命令用于手动生成快照。你也可以通过调用它们,手动让Redis进行数据集保存操作。

SAVE

SAVE命令会使用同步的方式生成RDB快照文件,这意味着在这个过程中会阻塞所有其他客户端的请求。因此不建议在生产环境使用这个命令,除非因为某种原因需要去阻止Redis使用子进程进行后台生成快照(例如调用fork(2)出错)。

BGSAVE

BGSAVE命令使用后台的方式保存RDB文件,调用此命令后,会立刻返回OK返回码。Redis会产生一个子进程进行处理并立刻恢复对客户端的服务。在客户端我们可以使用LASTSAVE命令查看操作是否成功。

127.0.0.1:6379> BGSAVE
Background saving started
127.0.0.1:6379> LASTSAVE
(integer) 1433936394
配置文件里禁用了快照生成功能不影响SAVE和BGSAVE命令的效果。

1.10 快照的运作方式

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

Redis 调用 fork() ,同时拥有父进程和子进程。

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

当子进程完成对新 RDB 文件的写入时,Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。

这种工作方式使得 Redis 可以从写时复制(copy-on-write)机制中获益。

2、AOF

快照并不是很可靠。如果你的电脑突然宕机了,或者电源断了,又或者不小心杀掉了进程,那么最新的数据就会丢失。而AOF文件则提供了一种更为可靠的持久化方式。每当Redis接受到会修改数据集的命令时,就会把命令追加到AOF文件里,当你重启Redis时,AOF里的命令会被重新执行一次,重建数据。

2.1 优点

比RDB可靠。你可以制定不同的fsync策略:不进行fsync、每秒fsync一次和每次查询进行fsync。默认是每秒fsync一次。这意味着你最多丢失一秒钟的数据。

AOF日志文件是一个纯追加的文件。就算是遇到突然停电的情况,也不会出现日志的定位或者损坏问题。甚至如果因为某些原因(例如磁盘满了)命令只写了一半到日志文件里,我们也可以用redis-check-aof这个工具很简单的进行修复。

当AOF文件太大时,Redis会自动在后台进行重写。重写很安全,因为重写是在一个新的文件上进行,同时Redis会继续往旧的文件追加数据。新文件上会写入能重建当前数据集的最小操作命令的集合。当新文件重写完,Redis会把新旧文件进行切换,然后开始把数据写到新文件上。

AOF把操作命令以简单易懂的格式一条接一条的保存在文件里,很容易导出来用于恢复数据。例如我们不小心用FLUSHALL命令把所有数据刷掉了,只要文件没有被重写,我们可以把服务停掉,把最后那条命令删掉,然后重启服务,这样就能把被刷掉的数据恢复回来。

2.2 缺点

在相同的数据集下,AOF文件的大小一般会比RDB文件大

在某些fsync策略下,AOF的速度会比RDB慢。通常fsync设置为每秒一次就能获得比较高的性能,而在禁止fsync的情况下速度可以达到RDB的水平。

在过去曾经发现一些很罕见的BUG导致使用AOF重建的数据跟原数据不一致的问题。

2.3 启用AOF
把配置项appendonly设为yes:

appendonly yes
文件路径和名称

# 文件存放目录,与RDB共用。默认为当前工作目录。
dir ./

# 默认文件名为appendonly.aof
appendfilename "appendonly.aof"
2.4 可靠性

你可以配置Redis调用fsync的频率,有三个选项:

1.每当有新命令追加到AOF的时候调用fsync。速度最慢,但是最安全。

2.每秒fsync一次。速度快(2.4版本跟快照方式速度差不多),安全性不错(最多丢失1秒的数据)。

3.从不fsync,交由系统去处理。这个方式速度最快,但是安全性一般。
推荐使用每秒fsync一次的方式(默认的方式),因为它速度快,安全性也不错。相关配置如下:

// appendfsync always
appendfsync everysec
appendfsync no

2.5 AOF日志重写

因为 AOF 的运作方式是不断地将命令追加到文件的末尾, 所以随着写入命令的不断增加, AOF 文件的体积也会变得越来越大。例如你递增一个计数器100次,那么最终结果就是数据集里的计数器的值为最终的递增结果,但是AOF文件里却会把这100次操作完整的记录下来。而事实上要恢复这个记录,只需要1个命令就行了,也就是说AOF文件里那100条命令其实可以精简为1条。所以Redis支持这样一个功能:在不中断服务的情况下在后台重建AOF文件

工作原理如下

以下是 AOF 重写的执行步骤:

Redis 执行 fork() ,现在同时拥有父进程和子进程。

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

对于所有新执行的写入命令,父进程一边将它们累积到一个内存缓存中,一边将这些改动追加到现有 AOF 文件的末尾: 这样即使在重写的中途发生停机,现有的 AOF 文件也还是安全的。

当子进程完成重写工作时,它给父进程发送一个信号,父进程在接收到信号之后,将内存缓存中的所有数据追加到新 AOF 文件的末尾。

搞定!现在 Redis 原子地用新文件替换旧文件,之后所有命令都会直接追加到新 AOF 文件的末尾。

我们可以通过配置设置日志重写的条件

# Redis会记住自从上一次重写后AOF文件的大小(如果自Redis启动后还没重写过,则记住启动时使用的AOF文件的大小)。
# 如果当前的文件大小比起记住的那个大小超过指定的百分比,则会触发重写。
# 同时需要设置一个文件大小最小值,只有大于这个值文件才会重写,以防文件很小,但是已经达到百分比的情况。

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
要禁用自动的日志重写功能,我们可以把百分比设置为0:

auto-aof-rewrite-percentage 0
Redis 2.4以上才可以自动进行日志重写,之前的版本需要手动运行BGREWRITEAOF这个命令。
2.6 数据损坏修复

服务器可能在程序正在对 AOF 文件进行写入时停机, 如果停机造成了 AOF 文件出错(corrupt), 那么 Redis 在重启时会拒绝载入这个 AOF 文件, 从而确保数据的一致性不会被破坏。

当发生这种情况时, 可以用以下方法来修复出错的 AOF 文件:

1.为现有的 AOF 文件创建一个备份。

2.使用 Redis 附带的 redis-check-aof 程序,对原来的 AOF 文件进行修复。
$ redis-check-aof –fix
(可选)使用 diff -u 对比修复后的 AOF 文件和原始 AOF 文件的备份,查看两个文件之间的不同之处。

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

3、 从RDB切换到AOF

这里只说Redis >= 2.2版本的方式:

备份一个最新的dump.rdb的文件,并把备份文件放在一个安全的地方。
运行以下两条命令:

$ redis-cli config set appendonly yes
$ redis-cli config set save ""

确保数据跟切换前一致。

确保数据正确的写到AOF文件里。

第二条命令是用来禁用RDB的持久化方式,但是这不是必须的,因为你可以同时启用两种持久化方式。

记得对配置文件redis.conf进行编辑启用AOF,因为命令行方式修改配置在重启Redis后就会失效。

4、RDB 和 AOF ,我应该用哪一个?

一般来说, 如果想达到足以媲美 PostgreSQL 的数据安全性, 你应该同时使用两种持久化功能。

如果你非常关心你的数据, 但仍然可以承受数分钟以内的数据丢失, 那么你可以只使用 RDB 持久化。

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

因为以上提到的种种原因, 未来我们可能会将 AOF 和 RDB 整合成单个持久化模型。 (这是一个长期计划。)

5、RDB 和 AOF 之间的相互作用

在版本号大于等于 2.4 的 Redis 中, BGSAVE 执行的过程中, 不可以执行 BGREWRITEAOF 。 反过来说, 在 BGREWRITEAOF 执行的过程中, 也不可以执行 BGSAVE 。

这可以防止两个 Redis 后台进程同时对磁盘进行大量的 I/O 操作。

如果 BGSAVE 正在执行, 并且用户显示地调用 BGREWRITEAOF 命令, 那么服务器将向用户回复一个 OK 状态, 并告知用户, BGREWRITEAOF 已经被预定执行: 一旦 BGSAVE 执行完毕, BGREWRITEAOF 就会正式开始。

当 Redis 启动时, 如果 RDB 持久化和 AOF 持久化都被打开了, 那么程序会优先使用 AOF 文件来恢复数据集, 因为 AOF 文件所保存的数据通常是最完整的。

6、备份 Redis 数据

先将下面这句话铭记于心: 一定要备份你的数据库

磁盘故障, 节点失效, 诸如此类的问题都可能让你的数据消失不见, 不进行备份是非常危险的。

Redis 对于数据备份是非常友好的, 因为你可以在服务器运行的时候对 RDB 文件进行复制: RDB 文件一旦被创建, 就不会进行任何修改。 当服务器要创建一个新的 RDB 文件时, 它先将文件的内容保存在一个临时文件里面, 当临时文件写入完毕时, 程序才使用 rename(2) 原子地用临时文件替换原来的 RDB 文件。

这也就是说, 无论何时, 复制 RDB 文件都是绝对安全的。

建议的方法

创建一个定期任务(cron job), 每小时将一个 RDB 文件备份到一个文件夹, 并且每天将一个 RDB 文件备份到另一个文件夹。

确保快照的备份都带有相应的日期和时间信息, 每次执行定期任务脚本时, 使用 find 命令来删除过期的快照: 比如说, 你可以保留最近 48 小时内的每小时快照, 还可以保留最近一两个月的每日快照。

至少每天一次, 将 RDB 备份到你的数据中心之外, 或者至少是备份到你运行 Redis 服务器的物理机器之外。

7、容灾备份

Redis 的容灾备份基本上就是对数据进行备份, 并将这些备份传送到多个不同的外部数据中心。

容灾备份可以在 Redis 运行并产生快照的主数据中心发生严重的问题时, 仍然让数据处于安全状态。

因为很多 Redis 用户都是创业者, 他们没有大把大把的钱可以浪费, 所以下面介绍的都是一些实用又便宜的容债备份方法:

Amazon S3 ,以及其他类似 S3 的服务,是一个构建灾难备份系统的好地方。 最简单的方法就是将你的每小时或者每日 RDB 备份加密并传送到 S3 。 对数据的加密可以通过 gpg -c 命令来完成(对称加密模式)。 记得把你的密码放到几个不同的、安全的地方去(比如你可以把密码复制给你组织里最重要的人物)。 同时使用多个储存服务来保存数据文件,可以提升数据的安全性。

传送快照可以使用 SCP 来完成(SSH 的组件)。 以下是简单并且安全的传送方法: 买一个离你的数据中心非常远的 VPS , 装上 SSH , 创建一个无口令的 SSH 客户端 key , 并将这个 key 添加到 VPS 的 authorized_keys 文件中, 这样就可以向这个 VPS 传送快照备份文件了。 为了达到最好的数据安全性,至少要从两个不同的提供商那里各购买一个 VPS 来进行数据容灾备份。

需要注意的是, 这类容灾系统如果没有小心地进行处理的话, 是很容易失效的。

最低限度下, 你应该在文件传送完毕之后, 检查所传送备份文件的体积和原始快照文件的体积是否相同。 如果你使用的是 VPS , 那么还可以通过比对文件的 SHA1 校验和来确认文件是否传送完整。

另外, 你还需要一个独立的警报系统, 让它在负责传送备份文件的传送器(transfer)失灵时通知你。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值