redis持久化

本文提供了关于redis持久化的技术描述,适用所有的redis用户阅读。如果想要更加全面地了解redis持久化及它提供的持久保障,你可能还需要阅读《redis持久化揭秘》

redis持久化

redis提供了不同幅度的持久化选项:

  • RDB持久化对你的数据集基于特定的时间间隔执行时间点快照。
  • AOF持久化在每次服务器收到写操作时记入日志,当服务器重启时,这些写操作会再次执行,重构出原始的数据集。
  • 命令以只能追加的方式记入日志,记入的格式与redis协议本身相同。当日志太大时,redis会重写日志。
  • 如果你想让你的数据只在服务器运行的时候存在,可以按照你的要求完全关闭持久化功能。
  • 可以在同一个实例中结合使用AOF和RDB。注意,在这种情况下,redis重启时使用AOF文件重构原始数据集,因为这样得到的数据集更完整。

最重要的事情就是理解RDB持久化和AOF持久化之间的差别与权衡。先从RDB开始:

RDB的优点

  • RDB是压缩的单个文件,表示你的某一时刻的redis数据。RDB文件非常适合备份。假如你把最近24小时中每个小时的RDB文件存档,并把最近30天每天存储一个RDB快照。这样遇到数据灾难时你就能容易地恢复各种版本的数据集了。
  • RDB适用于灾难恢复,作为一个单个的紧凑的文件,能够传输到远端的数据中心,或传到亚马逊S3(最好加密)。
  • RDB把redis的性能最大化。因为对于redis父进程,如果要执行持久化,唯一要做的就是创建一个子进程,而子进程会做所有的事情。父进程不需要执行磁盘I/O或者其它类似操作。
  • 对于数据集较大的情况,相较于AOF,RDB使得重启更快。

RDB的缺点

  • 在Redis停止工作的情况(例如断电)下,如果你想要使数据丢失的可能性最小,RDB并不合适。你可以设置不同的保存点,在保存点上会生成RDB(例如至少5分钟且100次对数据集的写操作以后。你也可以设置多个保存点)。然而,你通常会设置成每5分钟或更长时间生成一个RDB快照。在这种情况下,如果redis因为什么原因没有经过正常关机而停止工作,你会丢失最后几分钟的数据。
  • RDB需要经过fork()通过子进程写磁盘。如果数据集很大,fork()是非常耗时的,可能导致redis在几毫秒甚至1秒的时间里停止向客户端提供服务且CPU性能也不好。AOF也需要fork(),但你可以调节重新日志的频率而不需要任何牺牲。

AOF的优点

  • AOF更加可靠:你可以有不同的文件同步策略:没有文件同步,每秒同步,每次请求时同步。默认为每秒同步,写性能也不错(文件同步使用一个后台线程,当没有进行文件同步时,主线程会执行写操作),你只会丢失1秒内的写数据。
  • AOF的日志只能追加,因此也没有搜索操作,断电时也不会有丢失问题。即使由于某种原因(磁盘满或其它原因)导致最后一条命令只记录了一半,redis-check-aof工具也能很容易的修复它。
  • 当AOF文件太大时,redis能够在后台自动重写AOF。重写是完全安全的。因为当redis继续向旧文件追加内容时,产生的新文件包含能够产生当前数据集的所需要的最小命令集。一但新文件准备好了,redis就会切换到第二个文件,向这个新文件追加内容。
  • AOF使用一种方便理解和分析的格式,一条一条地记录所有操作的日志。你可以很容易地导入一个AOF文件。即使你由于错误地使用FLUSHALL命令冲掉了所有命令,如果在此期间没有没有重写日志,你仍然可以恢复数据,只需要停止服务器、移除最后一条命令,然后重启服务器就可以了。

AOF的缺点

  • 相较于相同数据集同等情况下的RDB文件来说,AOF文件通过很大。
  • 由于精确同步策略,AOF比RDB慢。通常情况下,每秒文件同步的性能仍然很好,而无文件同步的AOF和RDB的速度一样快,即使是在高负载的情况下。然而,对于大量的潜在问题,RDB还能提供更多的保障,即使是大规模的写。
  • 以前,我们对某些特殊的命令(例如一个涉及到阻塞的命令,BRPOPLPUSH)测出的bug很少,导致生成的AOF文件不能在重新加载时生成完全一样的数据集。这个bug不常见。我们在测试时自动创建随意的复杂的数据集并重新加载它们,检查是否一切正常。但这种问题在RDB持久中几乎不存在。更清楚地讲:Redis的AOF的工作原理是更新一个已经存在的状态,类似MySQL和MongoDB的作法,而RDB一次又一次地生成快照,这从理论上更健壮。然而,(1)注意,每次redis重写AOF时,它是从数据集中实际的数据开始,相对于一味向AOF追加(或重写时读取旧的AOF而不是内存中的数据)来说,这使它更强壮【1】。(2)我们至今没有发现一个来自用户的在真实使用中检测出AOF丢失数据的报告。

RDB还是AOF?

通常建议同时使用两种持久化方法,如果你希望数据安全性能够与PostgreSOL所提供的安全性相比。 
如果你关心数据,但仍能够允许在灾难时能够有几分钟的数据丢失,你可以只使用RDB。 
还有许多用户只使用AOF,但我们不推荐。因为实时的RDB快照对于数据库备份、快速重启都是很好的。 
注意:由于这些原因,我们倾向于在将来把AOF和RDB统一成一个持久化模型(长期计划)。 
下面的章节会对这两个持久化模型进行更详细的描述。

快照

默认情况下,redis把数据集的快照以二进制文件的保存到硬盘上,名为dump.rdb。你可以这样配置redis,当数据集至少发生M次变化时,每N秒保存数据集一次,你也可以手动调用SAVEBGSAVE命令。 
举个例子,这样配置,当数据集至少1000个键发生改变时,redis就会每60秒一次把数据集的保存(dump)到硬盘上。

save 60 1000
  • 1

这个策略被称为快照。

工作原理

当Redis要把数据集保存(dump)到硬盘时,会发生这些:

  • 创建子进程。现在有一个子进程和一个父进程了。
  • 子进程开始把数据集写到一个临时的RDB文件中。
  • 当子进程完成写RDB文件时,这个RDB文件替换原来的RDB文件。

这个该当使得Redis能够受益于写时复制。

仅追加文件

快照并不可靠。如果你的电脑上的redis停止运行,或电脑断电,或实例意外收到kill -9,最后写到redis的数据会丢失。对于有些应用来说,这可能不是什么大问题,但在有些需要完全持久化的用例中,这不是一个可行的选择。 
仅追加文件对于redis是可行的完全持久化的策略。从1.1版本开始可以使用可追加文件。 
你可以在你的配置文件中打开AOF。

appendonly yes
  • 1

从现在开始,每次redis收到一个会改变数据集(如SET)的命令,就会把它追加到AOF。当你重启redis,它会重新执行AOF中的命令来恢复状态。

日志重写

如你所想,随着写操作的执行,AOF变得越来越大。例如,假设你增加一个计数器100次,你在数据集中只有一个键和它的最终值,但在你的AOF中有100项。99项对于重建当前状态是不需要的。 
因此redis支持一个非常有趣的特性:它能够在后台重写AOF,而不会打断对客户端的服务。任何时候你执行BGREWRITEAOF,redis会把重建当前数据集所需的最少的命令序列写到内存。如果你在redis 2.2版本上使用AOF,你需要不时地运行BGREWRITEAOF。Redis 2.4版本会自动触发日志重写(查阅2.4版本的配置文件样例获得更多信息)。

仅追加文件有多可靠?

你可以配置redis将数据同步到硬盘的次数。有三个选项:

  • 每次有一个新的命令增加到AOF时进行文件同步。非常非常慢,非常安全。
  • 每秒文件同步。足够快(在2.4版本中,大概和快照一样快),如果发生灾难,会丢失1秒的数据。
  • 从不文件同步,由操作系统管控你的数据。更快,但不太安全。

建议(默认)策略是每秒同步。既快又相对安全。在实际操作中,第一种策略非常慢(尽管在2.0版本中做了改进),也不可能再快了。

AOF损坏时怎么做?

有可能在正在写AOF文件时服务器崩溃(这仍然不会导致不一致),这会损坏AOF文件,使它不能再被redis加载。你可能通过以下过程修复这个问题:

  • 备份你的AOF文件
  • 使用redis-check-aof工具修复原始文件,这个工具跟随redis一起发布:
$ redis-check-aof --fix
  • 1
  • 选择性地使用diff -u检查这两个文件有什么不同。
  • 使用修复的文件重启服务器。

工作原理

日志重写使用了与快照中使用的写时复制技术相同,这是它的工作原理。

  • redis创建一个子进程,现在有一个子进程和一个父进程了。
  • 子进程把新的AOF写到一个临时文件。
  • 父进程把所有新的改变积累到一个内存的缓冲区中(同时也会把新的改变写到旧的追加文件中,这样即使重写失败了也是安全的)。
  • 子进程完成重写后,父进程得到一个信号,把内存缓冲区的的命令追加到由子进程创建的新文件的结尾。
  • 好处!现在redis自动把新文件重命名为旧的文件名,开始把数据追加到新文件中。

如果我现在使用的是dump.rdb快照,我怎么切换到AOF? 
在2.0版本和2.2版本中,这个过程是不一样的。如你所想,在2.2版本中会简单点,不再需要重启。

redis 2.2以上版本

  • 备份最新的dump.rdb文件
  • 把备份文件转移到一个安全的地方
  • 执行下面这两个命令:
redis-cli config set appendonly yes
redis-cli config set save “”
  • 1
  • 2
  • 确认你的数据库包含的键的数目相同
  • 确认写操作会正确地添加到追加文件后面。

第一个CONFIG命令打开追加文件的使能。为了达到这个目的,Redis**会阻塞**并生成初始的dump,然后打开文件用于写,然后开始追加所有接下来的写请求。 
第二个CONFIG用于关闭快照持久化。这是可选的,你也可以同时打开两个持久化方法。 
重要:记得编辑你的redis.conf打开AOF,否则当你重启服务器时修改的配置会丢失,服务器又会启用旧的配置。

redis 2.0版本

  • 备份最新的dump.rdb文件
  • 把备份文件转移到一个安全的地方
  • 停止所有对数据库的写操作!
  • 在客户湍执行bgrewriteaof。这个创建一个仅追加属性的文件。
  • 当生成完AOF dump时停止服务器。
  • 编辑redis.conf,打开追加文件持久化的使能。
  • 重启服务器。
  • 确认你的数据库包含的键的数目相同
  • 确认写操作会正确地添加到追加文件后面。

AOF持久化与RDB持久化之间的交互

redis 2.4以上版本可以保证不会在执行RDB快照的时候触发AOF重写,也不会允许在AOF重写期间BGSAVE。这避免了两个redis后台进程同时做耗时的硬盘操作。当正在执行快照时,如果用户使用BGREWIRETEAOF命令显式地请求日志重写操作,服务器会返回OK的状态码,告诉用户这个操作被列入计划中,一早快照完成立即开始重写。 
在同时开启AOF和RDB的情况下,Redis重启时AOF文件会被用于重建原始数据集,因为这样能保证数据最完整。

备份Redis数据

在开始这一章节之前,请阅读这句话:务必备份数据库。硬盘损坏,云上的实例消失,等等。没有备份意味着数据清空的巨大风险。 
redis对于数据备份非常方便,你可以在数据库运行时拷贝RDB文件:RDB文件一但生成不会改变。由于生成时使用一个临时的名字,新的快照完成后它自动地使用rename(2)重命名成目标名字。 
这意味着在服务器运行时拷贝RDB文件是完全安全的。这是我们建议:

  • 在你的服务器创建一个长期作业,它负责每小时创建一次快照,并存放到同一个目录下,把每天的快照放在不同的目录下。
  • 每次运行作业脚本时,确保调用find命令以确认太旧的快照已被删除:例如你可以对最近的48小时做每小时快照,对最近的一两个月做每天快照。确保根据快照的数据和时间对快照命令。
  • 至少每天一次把RDB快照转移到数据中心以外或redis实例运行的机器以外。

灾难恢复

redis的灾难恢复实际上就是在备份功能的基础上,增加在不同外部数据中心之间传输备份的能力。通过这种方式,即使由于某个灾难事件影响到了redis所运行的数据中心及它所产生的快照,但数据仍然是安全的。 
由于许多redis的用户都处在创业阶段,并没有很多钱,因此我们回顾一下非常有趣但不需要太多花费的灾难恢复技术。

  • 亚马逊S3和其它相似的服务装备你的灾难恢复系统的好方式。只需要以加密的方式把每天或每小时的RDB快照上传到S3。你可以使用gpg 
    -c(对称加密模式)加密你的数据。确保把你的密码夏至许多不同的安全的地方(例如把一个复制版本交给你的组织中最重要的成员)。建议使用多个存储服务来增加数据的安全性。
  • 使用SCP(SSH的组成部分)把快照传到远端服务器。这是一种非常简单且安全的方法:在离你非常远的地方获取一个虚拟服务器,在那里安装ssh,生成一个不需要密码的ssh客户端密钥,把它加到你的虚拟服务器上的“认证的密钥”文件。你可以自动地传送备份文件 
    了。最好至少在两个不同的提供者那里获取两个虚拟服务器。

如果没有正确地编码,系统会很容易就挂掉,认识到这点很重要。至少一定要确认传输完成后查看文件大小(应该与原文件大小相同)。如果使用了VPS的话,最好还要确认一下SHA1的摘要。 
如果由于某种原因,传输备份文件不可以行的话,你需要一个独立的报警系统,

原文: 

阅读更多
文章标签: redis
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭