NoSQL之Redis---持久化(persistence)概念原理
Posted y-yg
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NoSQL之Redis---持久化(persistence)概念原理相关的知识,希望对你有一定的参考价值。
[不忘初心]
在Redis的命令中还有关于服务器的命令我们未做介绍,是由于其中的部分命令涉及持久化,集群等方面的内容。因此,本文我们就先来看看持久化部分的内容。好了,废话不表,马上开始我们的正文部分吧!
-------------------------------------------------------------------------------------------------------------------------------------
前言
本文提供关于Redis持久化的技术性描述,推荐所有Redis的用户都阅读。如果想更加广泛的了解Redis持久化和持久化所保证的耐久度,推荐阅读Redis的这篇介绍『http://oldblog.antirez.com/post/redis-persistence-demystified.html』
Redis持久化
- Redis提供了不同级别的持久化选项:
- RDB持久化可以在指定的时间间隔内生成数据集的时间点快照。
- AOF持久化记录了服务器所执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。AOF文件中的所有命令全部以Redis协议的格式来保存,新命令会被追加到文件的末尾。Redis还可以在后台对AOF文件进行重写,使得AOF文件的体积不会超过数据集状态所需的实际大小。
- 如果愿意的话,完全可以禁用持久化,使得数据只在服务器运行时存在。
- Redis还可以同时使用AOF和RDB。在这种情况下,Redis重新启动时会使用AOF文件来恢复数据集,因为其能够保证最完整的数据
理解RDB与AOF之间的差异点是十分重要的。接下来我们就逐一介绍RDB与AOF的相关内容
RDB的优点:
- RDB是一个非常进行的单文件,它保存了Redis某个时间点上数据集。RDB文件是非常适用于备份的。举个例子:你可以在最近的24小时内,每个小时进行一个备份,并且在每个月的每一天也进行一次备份。这种做法允许在发生问题的情况下,轻松地将数据集恢复到不同的版本上。
- RDB非常适用于灾难恢复,它只有一个非常紧凑的文件,可以被传送到别的数据中心,或者亚马逊S3中。
- RDB可以最大化Redis的性能,父进程在保存RDB文件时唯一要做的就是fork出一个子进程,然后这个子进程就会处理接下来的所有保存的工作,父进程将不再操作磁盘的I/O操作。
- RDB在回复大数据集时的速度要比AOF的回复速度要快。
RDB的缺点:
- 如果需要尽量避免在服务器故障时丢失数据,那么RDB不是一个好的选择。虽然你可以配置不同的保存点来控制RDB文件生成频率。但是因为RDB文件需要保存整个数据集的状态,所以这并不是一个非常轻松的操作。因此,你可能至少5分钟才会进行一个保存操作【具体配置方法我们后续介绍】,在这种情况下,Redis发生故障停机是,你可能会丢失最近几分钟内的所有数据。
- RDB需要在每次持久化是都要fork()出一个子进程,并且由子进程来完成持久化工作,当数据集非常大,或者CPU性能不足时,fork操作可能会非常耗时,甚至会造成Redis服务器在数毫秒乃至1秒钟内停止响应客户端的请求。虽然AOF也需要fork但是无论AOF重写的执行间隔有多么的长,数据的持久化都不会有任何的损失。
AOF的优点:
- 使用AOF持久化将会使得Redis变得十分耐久:你可以设置不同的fsync策略:no fsync,fsync every second,fsync at every query。默认情况下的策略为fsync every second,在这种配置下,Redis仍然能够保持良好的性能,即便是发生故障,最所也只是丢失1秒钟的数据。(fsync会在后台进程中执行,所以主线程可以尽可能的处理命令)
- AOF文件是一个只进行追加操作的日志文件,因此,对文件写入不需要进行seek操作,即使日志因为某些原因(如,磁盘已满,中途停机等)没有写入完整的命令,redis-check-aof工具也能够轻松的修复这种问题。
- Reids可以在AOF文件体积过大时,自动的在后台对AOF我呢见进行重写,重写后的新AOF文件包含了回复当前数据集所需的最小命令集合。整个重写的过程是绝对安全的,因为Redis在创建新的AOF文件时,仍然会继续将命令追加到现有的AOF文件里面,即使整个重写过程中发生付账,也不会导致现有的AOF文件丢失。并且,当新的AOF文件创建完成时,Redis就会用新的AOF文件来取代旧的文件,追加操作也会切换到新的AOF文件上。
- AOF文件有序的保存了对数据库执行的所有操作,这些操作以Redis协议的格式进行保存,因此,AOF文件的内容非常的容易被理解与分析。导出文件也十分轻松。举个例子,如果不小心执行了FLUSHALL命令,但是只要AOF文件没有被重写,那么停止服务器,除去AOF文件末尾的FLUSHALL命令,并且重新启动Redis,就可以恢复到FLUSHALL执行之前的状态了。
AOF的缺点:
- 对于相同的数据集,AOF文件的体积通常大于RDB文件的体积。
- 根据fsync的策略不同,AOF的速度可能会慢于RDB。在一般情况下,fsync every second 的性能仍然非常的高。而关闭fsync可以让AOF与RDB的速度一样快,即使在高负荷之下也是如此。不过在处理巨大的写载入时,RDB可以提供更加有保证的最大延迟。
- 在过去的一段时间,AOF出现了在特殊命令下的BUG(如阻塞命令BRPOPLPSH):导致了AOF文件在重新载入时,无法将数据集恢复成保存时的模样。这样的BUG是非常少见的,并且测试套件里针对这种情况添加了测试,自动生成随机的复杂数据集,并通过重新载入这些数据来保证一切正常。但是类似BUG在RDB中几乎是不可能出现的。为了更加清楚的了解这点:Redis AOF的自动增量式的更新现有的状态,如mysql,MongoDB那样,然而,RDB快照一次又一次的从头开始创建所有,在概念上更加的健壮与稳定。
- 然而这里还有一些事情需要关注:
- 每次AOF被Redis重写是从包含实际数据的数据集中从头开始创建的,使得BUG更加的容易出现,相比于一直对一个文件进行追加操作。(或者一个重写操作读取的是旧的AOF文件代替从内存中读取数据)
- 迄今为止,我们实际中还没有收到用户关于AOF错误问题的单一报告。
OK,我们该选择哪种模式呢?
- 一般情况下的建议是,如果想要达到PostgreSQL提供的数据分级安全,那么就需要同时使用AOF与RDB两种持久化策略。
- 如果你非常关心你的数据,但是仍然能够接受发生错误时,数分钟内的数据丢失,那么你可以只简单的使用RDB策略。
- 有很多用户只是用AOF策略。但是我们比推荐这中做法。因为定期的生成快照非常便于进行数据库备份。并且RDB备份的重载速度也优于AOF,除此之外,还能够避免之前问题所出现的提到的BUG。
- 注:对于上面我们提到的种种原因,未来我们会将AOF与RDB整合成为一个单一的持久化模型。(这是一个长期计划)
接下来的小节中,我们将介绍RDB与AOF的更多细节
RDB快照:
在默认情况下,Redis将数据库快照保存在名称为dump.rdb的二进制文件中。
你可以对Redis进行设置,让他在“N秒内数据集至少有M个改动”这一条件被满足时,自动保存一次数据集。或者手动的调用SAVE或者BGSAVE命令。
举个例子:如下的配置将会使得Redis自动的保存数据集,条件是“60秒内至少有1000个key被该改动”时触发。
save 60 1000这种保存策略我们就称为快照。
RDB快照的运行方式:
当Redis需要保存数据库时,服务器执行下面的操作:
- Redis调用fork(),同时拥有父进程,子进程。
- 子进程将数据库写入到一个临时的RDB文件中。
- 当子进程完成对RDB文件写操作时,用这个文件替换掉原来的RDB文件。
这个方式使得Redis可以从写时复制(copy-on-write)中获取益处.
Append-only file:
快照的功能并不是非常耐久的,如果Redis因为某些错误停机,那么服务器将丢失最近写入,但未保存到快照中的那些数据。尽管这些对某些应用来讲,数据的耐久性并不是最重要的考虑因素,但是对于那些需要完全耐久能力的程序来说,RDB不是一个明智的却则。从1.1版本开始,Redis增加了一种完全的持久化方式:AOF。在配置文件中设置如下内容:
appendonly yes配置之后,重新启动Redis并加载配置文件,每当Redis执行了一个改变数据集中的数据的命令是,这个命令就会被加载到AOF文件的末尾,这种做法,使得当重新启动Redis时,加载该AOF文件即可恢复完整的数据集。
AOF重写
正如我们能够猜到的那样,AOF文件将会随着写入命令的不断增加,变得越来越大。举个例子,我们对计数器counter增加100次,那么仅仅是为了保存这个计数器中最后的值,AOF文件需要使用100次记录。其中的99条记录对于恢复数据状态是非必需的。因此,Redis支持一个非常有趣的特性,他能够在后台重新建立AOF文件,而不打断对客户端的服务。当你执行一个BGREWRITEAOF命令时,Redis将会生成一个新的AOF文件,这个文件包含重建当前数据集所需的最少命令。
注:在2.4版本中需要手动触发,但是在2.4更高的版本中可以自动触发。具体内容可以参考2.4版本的示例配置文件
AOF有多么耐久?
你可以配置Redis多久才将fsync数据到磁盘,这里有三个选项:
fsync at every query:非常的慢,非常的安全。
fsync every second:足够快,并且在发生故障时最多1s的数据丢失。
no fsync:不使用aof,数据交给操作系统来处理,效率非常快,但是不安全。
推荐的(也是默认的)配置为:fsync every second 。其兼顾了速度与安全性。
AOF出错了怎么办?
在前面我们提到了服务器错误,导致AOF出错可能会丢失最近一段时间的数据,那么Redis在重启时,会拒绝载入这个AOF文件,从而确保数据一致性不会被破坏。当发生这种情况是你可以修复这个问题通过下面的方法:
- 为现有的AOF文件进行备份。
- 使用Redis负载的redis-check-aof工具来对原来的AOF文件进行修复。
redis-check-aof --fix
- 可选的,使用diff -u 对比修复后的AOF文件与原始AOF的备份,查看两份文件不同之处。
- 重启Redis服务器,等待服务器载入修复后的AOF文件,并进行数据恢复。
AOF的工作方式
AOF重写机制使用了与RDB快照一样的写时复制控制,下面是这个其具体的工作细节:
- Redis执行fork,同时拥有父进程与子进程。
- 子进程开始将AOF文件写到临时文件中。
- 父进程累积所有新的变化到内存缓存中。(同时将是新的变化写入旧的AOF文件中,这样即使在重写中发生故障,也能保证数据是安全的)
- 当子进程完成重写文件时,父进程会得到一个信号,之后,将内存中的缓存数据追加到新的AOF文件末尾。
- 搞定!现在Redis原子的替换掉有文件,之后所有的文件追加动作都会针对新的AOF文件进行。
如果我正在使用RDB快照模式,怎么切换到AOF文件?
这里我们仅仅翻译2.2版本之上的做法:在2.2版本之上,并不需要进行重启。
- 为最新的dump.rdb文件创造备份文件。
- 将备份文件放在一个安全的地方。
- 执行下面的两条命令:
redis-cli> config set appendonly yesredis-cli> config set save ""
- 确保命令执行之后,数据库的键的数量没有改变。
- 确保写命令会被正确的追加到AOF文件的末尾。
上面第一个CONFIG命令开启了AOF功能,目的是阻塞Redis直到初始AOF文件创建完成,之后Redis会继续处理命令请求,并开始将写入命令追加到AOF文件末尾。
第二条CONFIG命令用于关闭RDB快照功能。这一步是可选的,如果你愿意的话,也可以同时使用RDB和AOF这两种持久化功能。
重要提醒:记得在redis.conf文件中打开AOF功能!否则,服务器重启之后,之前的设置就会被忽略,启动过程会按照老的配置执行。
AOF与RDB之间的相互作用:
在大于2.4版本中,尽量避免在执行RDB快照的过程中执行AOF文件的重写,或者在AOF重写过程中不允许执行BGSAVE命令。这可以防止两个Redis进程同时对磁盘尽量大量的I/O操作。
当正在进行快照操作时,并且用户显示的调用了BGREWRITEAOF命令执行写操作,服务器将会给客户端回复一个OK,告知用户操作已经进入命令执行队列,一旦RDB快照结束,命令就会被执行。
当AOF模式与RDB模式都被打开时,在Redis重新启动时,会有限使用AOF文件进行数据集恢复,因为AOF文件通常情况下都比较完整,
备份Redis数据:
在阅读本小节之前,请一定记住这句话:一定记得备份你的数据库!
磁盘故障,节点失效等等问题,都可能让数据消失,不数据备份是非常危险的。
Redis对于数据备份是非常友好的,因为你可以在服务器运行时,对RDB文件进行复制,RDB文件一旦被创建,就不会进行任何的修改,当服务器要创建一个新的RDB文件是,他先将文件内容保存在一个临时文件里面,当临时文件写入完毕时,程序才使用rename原子的用临时文件替换原理的RDB文件。
这也就是说,我们复制RDB文件都是非常安全的,因此,我们有如下的建议:
创建一个定时任务,每一个小时将一个RDB文件备份到一个文件夹,并且每天将一个RDB文件备份到另一个文件夹。
当后台执行定时任务时,确保调用find命令来删除过期的RDB快照,举个例子:你可以在最近的48小时之内每个小时都创建一个RDB快照,还可以,保留最近1-2月内每天的快照。(这种做法需要确保快照的备份都带有相应的时间信息)
至少每天一次,将RDB文件备份到你的数据中心外,或者至少,将数据备份到Redis服务器的物理机器之外。
容灾备份:
Redis的容灾备份基本上就是对数据进行备份,并将这些备份到多个不同的外部数据中心。容灾备份可以在Redis运行并产生快照的主数据中心发生严重的问题时,仍然让数据处于安全状态。
由于Redis的使用者很多都是创业者,他们没有足够的钱来浪费,所以,下面我们给出一些实用且廉价的容灾备份方法。
- Amazon S3,以及其他类似的服务,是一个构建容灾备份系统的好地方。最简单的方法就是将你的每小时,每天的RDB快照加密传送到S3服务中。对数据的加密可以通过“gpg -c”命令完成(对称加密模式)。同时确保把你的密码放置到不同的安全的地方。(比如把密码交给组织结构中关键人物)。另外,推荐的做法是:使用多个存储服务来提高数据的安全性。
- 传送快照可以使用SCP(SSH的组件)来完成传输。一下是简单并且安全的传送方法:购买一个离数据中心较远的VPS,装上SSH,创建一个无密码的SSH客户端key,并将这个key添加到VPS的授权文件中,这样就可以向这个VPS传送备份的快照文件了。为了达到最好的数据安全性,最少要从两个不同的提供商那里购买一个VPS来进行数据容灾备份。
重要提示:容灾系统在错误的处理方式下变得很容易失效。在最低限度下,你应该在文件传送完毕之后,检查所传送的备份文件的体积和原始快照文件的体积是否相同。如果使用的VPS,那么还可以通过对比文件的SHA1校验和来确认文件是否传送完整。
另外,你还需要一个独立的警报系统,让它在稳份文件因为某些原因停止工作时通知你。
-------------------------------------------------------------------------------------------------------------------------------------
至此,NoSQL之Redis---持久化(persistence)概念原理 结束
参考资料:
官方文档:http://redis.io/topics/persistence
其他资料:http://doc.redisfans.com/topic/persistence.html
以上是关于NoSQL之Redis---持久化(persistence)概念原理的主要内容,如果未能解决你的问题,请参考以下文章
Redis Persistence 之 redis database