redis有两种持久化方案:
-
RDB
:以指定时间间隔对数据集进行备份(全量备份); -
AOF
:AOF模式记录server端接收的每个写入操作,将在服务器启动时再次播放,重建原始数据集。它以追加的方式记录数据(有点类似增量,但又不是增量,因为这里只记录的式操作,而不是数据)。当数据量较大时,还可以使用重写来压缩文件。
RDB优点
- RDB是Redis数据的一个非常紧凑的单文件时间点表示。它非常适合备份。例如,您可能希望在最近24小时内每小时归档您的RDB文件,并且每天保存RDB快照持续30天。这使您可以在发生灾难时轻松恢复数据集的不同版本。
- RDB非常适合灾难恢复,可以将单个压缩文件传输到远端数据中心,也可以传输到Amazon S3(可能是加密的)。
- RDB最大限度地提高了Redis的性能,因为Redis父进程只负责接收操作,执行RBD时唯一工作就是
fork
一个子进程完成所有其余工作。父实例永远不会执行磁盘I/O或类似操作。 - 数据量大时,重启速度比AOF快
RDB缺点
- 耐久性并不是很好。当主机宕机时,丢失数据会比较多。例如你设置5分钟内100次写入就进行一次备份,则这会导致你最少丢失最新的5分钟内的数据。但一般都会比5分钟长,所以丢失数据会更多。
- 如果数据量很大且cpu性能不好时,可能会导致主进程停止接收命令几毫秒甚至1秒。
AOF优点
- 更高的耐久性,AOF支持三种同步策略:
- appendfsync no:只需让操作系统在需要时刷新数据。速度快。
- appendfsync everysec (默认):fsync每秒只有一次。折中。
- appendfsync always:每次写入仅附加日志后的fsync。慢,最安全。
使用fsync的默认策略,每秒写入性能仍然很好(使用后台线程执行fsync,并且当没有fsync正在进行时,主线程将努力执行写入。)
- AOF日志是仅附加日志,因此如果停电,则没有搜索,也没有损坏问题。即使由于某种原因(磁盘已满或其他原因)日志以半写命令结束,
redis-check-aof
工具也能够轻松修复它。 - 当Redis太大时,Redis能够在后台自动重写AOF。重写是完全安全的,因为重写时Redis继续往旧文件写入,使用创建当前数据集所需的最小操作集生成一个全新的文件,并且一旦第二个文件准备就绪,Redis会切换两个并开始附加到新的那一个。
- AOF以易于理解和解析的格式一个接一个地包含所有操作的日志。甚至你可以轻松的修改AOF文件。例如你不小心执行了
FLUSHALL
,只要Redis还未执行重写,你可以修改AOF文件删除FLUSHALL,重新启动Redis就可以了。
AOF缺点
- 数据量一样AOF文件要比RDB大
- 根据不同的同步策略,AOF可能比RDB慢。一般来说,fsync设置为每秒性能仍然非常高,并且在fsync禁用的情况下,即使在高负载下也应该与RDB一样快。即使在写入负载很大的情况下,RDB仍能够提供有关最大延迟的更多保证。因为AOF同步频率比RDB高,应该会有点影响。
- 在过去,我们在特定命令中遇到了罕见的错误()导致生成的AOF在重新加载时不会重现完全相同的数据集。这个错误很少见,我们在测试套件中进行测试,自动创建随机复杂数据集并重新加载它们以检查一切正常,但RDB持久性几乎不可能出现这种错误。为了更清楚地说明这一点:Redis AOF逐步更新现有状态,如MySQL或MongoDB,而RDB快照一次又一次地创建所有内容,这在概念上更加健壮。然而 -1) 应该注意的是,每次通过Redis重写AOF时,都会从数据集中包含的实际数据开始从头开始重新创建,与始终附加的AOF文件相比,可以更好地抵抗错误(或者重写一个旧的AOF而不是读取内存中的数据)-2) 我们从未收到用户提供过关于在现实世界中检测到的AOF损坏的单一报告。
应该使用哪一种?
一般的迹象是,如果您希望一定程度的数据安全性与PostgreSQL为您提供的数据安全性相当,则应使用两种持久性方法。
如果你非常关心你的数据,但是能忍受在发生灾难的情况下仍然会有几分钟的数据丢失,你可以单独使用RDB。
不建议单独使用AOF。
快照
默认情况下,Redis将数据集的快照保存在名为dump.rdb的二进制文件中。如果数据集中至少有M个更改,则可以将Redis配置为每N秒保存数据集,或者您可以手动调用SAVE
或BGSAVE
命令。
例如,以下设置表示每60秒内至少更改了1000个key会使Redis进行一次自动备份
save 60 1000
此策略称为快照。
工作流程
每当Redis需要将数据集转储到磁盘时,就会发生以下情况:
- fork一个子进程。我们现在有一个子进程和一个父进程。
- 子进程开始将数据集写入临时RDB文件。
- 当子进程完成编写新的RDB文件后,它将替换旧文件。
此方法允许Redis受益于写时复制语义。
Append-only file
快照不是很耐用。如果运行Redis的计算机停止运行,电源线出现故障,或者您意外杀死了实例,则Redis上写入的最新数据将丢失。虽然这对某些应用程序来说可能不是什么大问题,但是有完整持久性的用例,在这些情况下,Redis不是一个可行的选择。
仅附加文件是Redis的另一种完全持久的策略。它在1.1版中可用。 您可以在配置文件中打开AOF:
appendonly yes
从现在开始,每次Redis收到更改数据集(例如SET
)的命令时,它都会将其附加到AOF。重新启动Redis时,它将重新播放AOF以重建数据集。
日志重写
你可以猜到,随着执行写操作,AOF变得越来越大。例如,如果您将计数器递增100次,则最终会在数据集中包含一个包含最终值的单个键,但在AOF中会有100个条目。重建当前状态可以去除其中99个条目。
所以Redis支持一个有趣的功能:它能够在后台重建AOF而不会中断对客户端的服务。每当您发出BGREWRITEAOF
命令时,Redis都会编写在内存中重建当前数据集所需的最短命令序列。如果您在Redis 2.2中使用AOF,则需要不时运行BGREWRITEAOF
。Redis 2.4能够自动触发日志重写
append only的耐久性
您可以配置Redis将在磁盘上同步数据的次数。有三种选择:
- appendfsync always:fsync每次将新命令追加到AOF。非常非常慢,非常安全。
- appendfsync everysec:fsync每秒。足够快(2.4可能与快照一样快),如果发生灾难,您可能会丢失1秒的数据。
- appendfsync no:从不fsync,只需将数据放在操作系统的手中。更快,更不安全的方法。通常情况下,Linux将使用此配置每30秒刷新一次数据,但这取决于内核的精确调整。
建议的(和默认)策略是每秒fsync。它非常快速且非常安全。a;ways
策略在实践中非常慢,但它支持组提交,因此如果有多个并行写入,Redis将尝试执行单个fsync操作。
如果我的AOF被截断,我该怎么办?
服务器可能在写入AOF文件时崩溃,或者存储AOF文件的卷存储已满。发生这种情况时,AOF仍然包含表示数据集的给定时间点版本的一致数据(使用默认的AOF fsync策略可能会持续一秒钟),但是AOF中的最后一个命令可能会被截断。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
如果需要,您可以更改默认配置以强制Redis在此类情况下停止,但无论文件中的最后一个命令格式不正确,都要继续默认配置,以确保重新启动后可用。
旧版本的Redis可能无法恢复,可能需要执行以下步骤:
- Make a backup copy of your AOF file.
- 使用Redis附带的
redis-check-aof
工具修复原始文件:
$ redis-check-aof --fix - (可选)使用
diff -u
来检查两个文件之间的区别。 - 使用固定文件重新启动服务器。
如果我的AOF被破坏了该怎么办?
如果AOF文件不仅被截断,而是在中间被无效的字节序列破坏,那么事情就更复杂了。 Redis会在启动时抱怨并将中止:
* 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>
最好的办法是运行redis-check-aof
实用程序,最初没有--fix选项,然后理解问题,跳转到文件中的给定偏移量,看看是否可以手动修复文件: AOF使用相同格式的Redis协议,手动修复非常简单。否则可以让实用程序为我们修复文件,但是在这种情况下,从无效部分到文件末尾的所有AOF部分都可能被丢弃,如果发生损坏,会导致大量数据丢失在文件的初始部分。
最好手动修复
重写是怎么工作的?
日志重写使用与快照的相同的写时复制技巧。这是它的工作原理:
- fork子进程,所以现在我们有了一个子进程和一个父进程。
- 子进程开始在临时文件中写入新的AOF。
- 父进程会在内存缓冲区中累积所有新更改(但同时它会将旧更改写入旧的AOF文件中,因此如果重写失败,我们就是安全的)。
- 当子进程重写文件时,父进程会获得一个信号,并在子进程生成的文件末尾附加内存缓冲区。
- 现在,Redis以原子方式将旧文件重命名为新文件,并开始将新数据附加到新文件中。
此时父进程可能会阻塞。
如果我当前正在使用dump.rdb快照,如何切换到AOF?
在Redis 2.0和Redis 2.2中执行此操作有不同的过程,因为您可以猜测它在Redis 2.2中更简单,并且根本不需要重新启动。
Redis >= 2.2
- 备份最新的dump.rdb文件。
- 将此备份转移到安全的地方。
- 发出以下两个命令:
- redis-cli config set appendonly yes
- redis-cli config set save ""
- 确保您的数据库包含相同数量的key。
- 确保写入正确附加到仅附加文件。
第一个CONFIG命令启用AOF。为了做到这一点,Redis将阻止生成初始dump,然后将打开文件进行写入,并将开始附加所有下一个写入查询
第二个CONFIG命令用于关闭快照持久性。如果您希望可以同时启用持久性方法,则这是可选的。
重要提示:请记住一定要编辑
redis.conf
以打开AOF,否则当您重新启动服务器时,配置更改将丢失,服务器将使用旧配置重新启动。
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.
AOF和RDB持久性之间的相互作用
Redis>= 2.4确保在RDB快照操作正在进行时避免触发AOF重写,或者在AOF重写正在进行时允许BGSAVE。这可以防止两个Redis后台进程同时执行大量磁盘I/O。
当快照正在进行且用户使用BGREWRITEAOF
明确请求日志重写操作时,服务器将回复一个OK状态代码,告诉用户操作已安排,并且一旦快照完成,重写将开始。
在启用AOF和RDB持久性并且Redis重新启动的情况下,AOF文件将用于重建原始数据集,因为它保证是最完整的。
备份Redis数据
在开始本节之前,请务必阅读以下句子:确保备份您的数据库。磁盘损坏,云中的实例消失,等等:没有备份意味着数据消失在/dev/null中的巨大风险。
Redis非常适合数据备份,因为您可以在数据库运行时复制RDB文件:RDB一旦生成就永远不会被修改,并且在生成它时会使用临时名称,并且只有在新快照完成时才使用rename(2)以原子方式重命名为最终目标。
这意味着在服务器运行时复制RDB文件是完全安全的。这就是我们的建议:
- 在服务器中创建一个cron定时任务,在一个目录中创建RDB文件的每小时快照,在另一个目录中创建每日快照。
- 每次运行cron脚本时,请确保调用find命令以确保删除过旧的快照:例如,您可以保存最近48小时的每小时快照,以及一到两个月的每日快照。确保使用数据和时间信息命名快照。
- 每天至少有一次确保在数据中心外部或至少在运行Redis实例的物理机器外部传输RDB快照。
如果运行仅启用AOF持久性的Redis实例,则仍可以复制AOF以创建备份。该文件可能缺少最后一部分,但Redis仍然可以加载它(请参阅前面有关截断的AOF文件的部分)。
容灾
Redis环境中的灾难恢复基本上与备份相同,并且能够在许多不同的外部数据中心中传输这些备份。这样,即使在某些灾难性事件影响Redis正在运行并生成其快照的主数据中心的情况下,数据也是安全的。
由于许多Redis用户都处于启动阶段,因此没有足够的资金支出,我们将审查最有趣的灾难恢复技术,这些技术的成本不会太高。
- Amazon S3和其他类似服务是实施灾难恢复系统的好方法。只需以加密形式将每日或每小时RDB快照传输到S3即可。您可以使用gpg -c加密数据(在对称加密模式下)。确保将密码存储在许多不同的安全位置(例如,将副本提供给组织中最重要的人员)。建议使用多个存储服务以提高数据安全性。
- 使用SCP(SSH的一部分)将快照传输到远程服务器。这是一个相当简单和安全的途径:在离你很远的地方获得一个小VPS,在那里安装ssh,并生成一个没有密码短语的ssh客户端密钥,然后将其添加到小VPS的authorized_keys文件中。您已准备好以自动方式传输备份。在两个不同的提供商中获得至少两个VPS以获得最佳结果。
重要的是要理解,如果没有以正确的方式实施,该系统很容易失败。至少要确保在传输完成后您能够验证文件大小(应该与您复制的文件相匹配)以及可能的SHA1摘要(如果您使用的是VPS)。
如果由于某种原因传输新备份不起作用,您还需要某种独立的警报系统。