《Redis官方文档》持久化

原文链接 译者:Alexandar Mahone

这篇文章从技术层面描述了Redis持久化,建议所有读者阅读。如果希望更多了解Redis持久化和持久性保障,建议阅读Redis持久化揭秘

Redis 持久化

提供了多种不同级别的持久化方式:

  • RDB 持久化可以在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot)。
  • AOF 持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。 AOF 文件中的命令全部以 Redis 协议的格式来保存,新命令会被追加到文件的末尾。 Redis 还可以在后台对 AOF 文件进行重写(rewrite),使得 AOF 文件的体积不会超出保存数据集状态所需的实际大小。Redis 还可以同时使用 AOF 持久化和 RDB 持久化。 在这种情况下, 当 Redis 重启时, 它会优先使用 AOF 文件来还原数据集, 因为 AOF 文件保存的数据集通常比 RDB 文件所保存的数据集更完整。你甚至可以关闭持久化功能,让数据只在服务器运行时存在。

了解 RDB 持久化和 AOF 持久化之间的异同是非常重要的, 以下几个小节将详细地介绍这这两种持久化功能, 并对它们的相同和不同之处进行说明。

RDB 的优点:

  • RDB是一种表示某个即时点的Redis数据的紧凑文件。RDB文件适合用于备份。例如,你可能想要每小时归档最近24小时的RDB文件,每天保存近30天的RDB快照。这允许你很容易的恢复不同版本的数据集以容灾。
  • RDB非常适合于灾难恢复,作为一个紧凑的单一文件,可以被传输到远程的数据中心,或者是Amazon S3(可能得加密)。
  • RDB最大化了Redis的性能,因为Redis父进程持久化时唯一需要做的是启动(fork)一个子进程,由子进程完成所有剩余工作。父进程实例不需要执行像磁盘IO这样的操作。
  • RDB在重启保存了大数据集的实例时比AOF要快。

RDB 的缺点

  • 当你需要在Redis停止工作(例如停电)时最小化数据丢失,RDB可能不太好。你可以配置不同的保存点(save point)来保存RDB文件(例如,至少5分钟和对数据集100次写之后,但是你可以有多个保存点)。然而,你通常每隔5分钟或更久创建一个RDB快照,所以一旦Redis因为任何原因没有正确关闭而停止工作,你就得做好最近几分钟数据丢失的准备了。
  • RDB需要经常调用fork()子进程来持久化到磁盘。如果数据集很大的话,fork()比较耗时,结果就是,当数据集非常大并且CPU性能不够强大的话,Redis会停止服务客户端几毫秒甚至一秒。AOF也需要fork(),但是你可以调整多久频率重写日志而不会有损(trade-off)持久性(durability)。

AOF 的优点:

  • 使用AOF Redis会更具有可持久性(durable):你可以有很多不同的fsync策略:没有fsync,每秒fsync,每次请求时fsync。使用默认的每秒fsync策略,写性能也仍然很不错(fsync是由后台线程完成的,主线程继续努力地执行写请求),即便你也就仅仅只损失一秒钟的写数据。
  • AOF日志是一个追加文件,所以不需要定位,在断电时也没有损坏问题。即使由于某种原因文件末尾是一个写到一半的命令(磁盘满或者其他原因),redis-check-aof工具也可以很轻易的修复。
  • 当AOF文件变得很大时,Redis会自动在后台进行重写。重写是绝对安全的,因为Redis继续往旧的文件中追加,使用创建当前数据集所需的最小操作集合来创建一个全新的文件,一旦第二个文件创建完毕,Redis就会切换这两个文件,并开始往新文件追加。
  • AOF文件里面包含一个接一个的操作,以易于理解和解析的格式存储。你也可以轻易的导出一个AOF文件。例如,即使你不小心错误地使用FLUSHALL命令清空一切,如果此时并没有执行重写,你仍然可以保存你的数据集,你只要停止服务器,删除最后一条命令,然后重启Redis就可以。

AOF 的缺点:

  • 对同样的数据集,AOF文件通常要大于等价的RDB文件。
  • AOF可能比RDB慢,这取决于准确的fsync策略。通常fsync设置为每秒一次的话性能仍然很高,如果关闭fsync,即使在很高的负载下也和RDB一样的快。不过,即使在很大的写负载情况下,RDB还是能提供能好的最大延迟保证。
  • 在过去,我们经历了一些针对特殊命令(例如,像BRPOPLPUSH这样的阻塞命令)的罕见bug,导致在数据加载时无法恢复到保存时的样子。这些bug很罕见,我们也在测试套件中进行了测试,自动随机创造复杂的数据集,然后加载它们以检查一切是否正常,但是,这类bug几乎不可能出现在RDB持久化中。为了说得更清楚一点:Redis AOF是通过递增地更新一个已经存在的状态,像MySQL或者MongoDB一样,而RDB快照是一次又一次地从头开始创造一切,概念上更健壮。但是,1)要注意Redis每次重写AOF时都是以当前数据集中的真实数据从头开始,相对于一直追加的AOF文件(或者一次重写读取老的AOF文件而不是读内存中的数据)对bug的免疫力更强。2)我们还没有收到一份用户在真实世界中检测到崩溃的报告。

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

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

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

有很多用户单独使用AOF,但是我们并不鼓励这样,因为时常进行RDB快照非常方便于数据库备份,启动速度也较之快,还避免了AOF引擎的bug。

注意:基于这些原因,将来我们可能会统一AOF和RDB为一种单一的持久化模型(长远计划)。

下面的部分将介绍两种持久化模型等多的细节。

RDB 快照

默认情况下,Redis保存数据集快照到磁盘,名为dump.rdb的二进制文件。你可以设置让Redis在N秒内至少有M次数据集改动时保存数据集,或者你也可以手动调用SAVE或者BGSAVE命令。

例如,这个配置会让Redis在每个60秒内至少有1000次键改动时自动转储数据集到磁盘:

save 60 1000

这种策略被称为快照。

快照的运作方式:

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

  • Redis 调用 fork() ,同时拥有父进程和子进程。
  • 子进程将数据集写入到一个临时 RDB 文件中。
  • 当子进程完成对新 RDB 文件的写入时,Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。

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

只追加文件 AOF

快照功能并不是非常耐久(durable): 如果 Redis 因为某些原因而造成故障停机, 那么服务器将丢失最近写入、且仍未保存到快照中的那些数据。尽管对于某些程序来说, 数据的耐久性并不是最重要的考虑因素, 但是对于那些追求完全耐久能力(full durability)的程序来说, 快照功能就不太适用了。

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

你可以通过修改配置文件来打开 AOF 功能:
appendonly yes
从现在开始, 每当 Redis 执行一个改变数据集的命令时(比如 SET), 这个命令就会被追加到 AOF 文件的末尾。 当 Redis 重新启时, 程序就可以通过重新执行 AOF 文件中的命令来达到重建数据集的目的。

日志重写

你可以猜得到,写操作不断执行的时候AOF文件会越来越大。例如,如果你增加一个计数器100次,你的数据集里只会有一个键存储这最终值,但是却有100条记录在AOF中。其中99条记录在重建当前状态时是不需要的。

于是Redis支持一个有趣的特性:在后台重建AOF而不影响服务客户端。每当你发送BGREWRITEAOF时,Redis将会写入一个新的AOF文件,包含重建当前内存中数据集所需的最短命令序列。如果你使用的是Redis 2.2的AOF,你需要不时的运行BGREWRITEAOF命令。Redis 2.4可以自动触发日志重写(查看Redis 2.4中的示例配置文件以获得更多信息)。

AOF持久性如何?

你可以配置 Redis 多久才将数据 fsync 到磁盘一次。有三个选项:

  • 每次有新命令追加到 AOF 文件时就执行一次 fsync :非常慢,也非常安全。
  • 每秒 fsync 一次:足够快(和使用 RDB 持久化差不多),并且在故障时只会丢失 1 秒钟的数据。
  • 从不 fsync :将数据交给操作系统来处理。更快,也更不安全的选择。

推荐(并且也是默认)的措施为每秒 fsync 一次, 这种 fsync 策略可以兼顾速度和安全性。 总是 fsync 的策略在实际使用中非常慢, 即使在 Redis 2.0 对相关的程序进行了改进之后仍是如此 —— 频繁调用 fsync 注定了这种策略不可能快得起来。

如果 AOF 文件出错了,怎么办?

服务器可能在程序正在对 AOF 文件进行写入时崩溃(这个不应该破坏数据的一致性), Redis不会装载已破坏的AOF文件。当发生这种情况时, 可以用以下方法来修复出错的 AOF 文件:

  • 为现有的 AOF 文件创建一个备份。
  • 使用 Redis 附带的 redis-check-aof 程序,对原来的 AOF 文件进行修复。
  • $ redis-check-aof –fix
  • (可选)使用 diff -u 对比修复后的 AOF 文件和原始 AOF 文件的备份,查看两个文件之间的不同之处。
  • 重启 Redis 服务器,等待服务器载入修复后的 AOF 文件,并进行数据恢复。

如何工作

日志重写采用了和快照一样的写时复制机制。下面是过程:

  • Redis调用fork()。于是我们有了父子两个进程。
  • 子进程开始向一个临时文件中写AOF。
  • 父进程在一个内存缓冲区中积累新的变更(同时将新的变更写入旧的AOF文件,所以即使重写失败我们也安全)。
  • 当子进程完成重写文件,父进程收到一个信号,追加内存缓冲区到子进程创建的文件末尾。
  • 搞定!现在Redis原子性地重命名旧文件为新的,然后开始追加新数据到新文件。

如何由RDB持久化转换到AOF持久化?

Redis 2.0 和 Redis 2.2 处理流程不一样,可以很简单猜测到 Redis 2.2 处理流程更简单,并且不需要重启。

Redis >=2.2 时

  • 创建最近的RDB文件的备份。
  • 将备份保存在安全的位置。
  • 发起如下命令。
  • $redis-cli config set appendonly yes。
  • $redis-cli config set save “”。
  • 确认数据库包含相同的keys。
  • 确认write操作被正确追加到了AOF文件。

第一个CONFIG命令开启AOF。Redis会阻塞以生成初始转储文件,然后打开文件准备写,开始追加写操作。

第二个CONFIG命令用于关闭快照持久化。这一步是可选的,如果你想同时开启这两种持久化方法。

重要:记得编辑你的redis.conf文件来开启AOF,否则当你重启服务器时,你的配置修改将会丢失,服务器又会使用旧的配置。

Redis2.0时

  • 创建最近的RDB文件的备份;
  • 将备份存放在安全的位置;
  • 停止数据库上的所有写操作;
  • 发起 redis-cli bgrewriteaof命令创建AOF文件;
  • 当AOF文件生成后停止Redis Server;
  • 编辑redis.conf开启AOF持久化;
  • 重启Redis Server;
  • 确认数据库包含相同的keys;
  • 确认write操作被正确追加到了AOF文件。

AOF与RDB之间的相互作用

Redis2.4以上的版本会确保在RDB快照创建时不触发AOF重写或者在AOF重写时不允许BGSAVE操作,以避免Redis后台进程同时做繁重的磁盘I/O操作。

当创建RDB快照时对于用户使用BGREWRITEAOF明确发起的日志重写操作server会立刻回应一个ok状态码告知用户操作将回被执行,当且仅当快照创建完成后重写操作开始被执行。

在同时使用了AOF和RDB方式的情况下,Redis重启后会优先使用AOF文件来重构原始数据集。

备份Redis 数据

开始这一部分之前,请务必牢记:一定要备份你的数据库。磁盘损坏,云中实例丢失,等等:没有备份意味着丢失数据的巨大风险。

Redis对数据备份非常友好,因为你可以在数据库运行时拷贝RDB文件:RDB文件一旦生成就不会被修改,文件生成到一个临时文件中,当新的快照完成后,将原子性地使用rename(2)修改文件名为目标文件。

这意味着,在服务器运行时拷贝RDB文件是完全安全的。以下是我们的建议:

  • 创建一个定时任务(cron job),每隔一个小时创建一个RDB快照到一个目录,每天的快照放在不同目录。
  • 每次定时脚本运行时,务必使用find命令来删除旧的快照:例如,你可以保存最近48小时内的每小时快照,一到两个月的内的每天快照。注意命名快照时加上日期时间信息。
  • 至少每天一次将你的RDB快照传输到你的数据中心之外,或者至少传输到运行你的Redis实例的物理机之外。

灾难恢复

在Redis中灾难恢复和数据备份基本上是同样的过程,并且灾难恢复会将这些备份传输到外部的多个数据中心。这样即使一些灾难性的事件影响到运行Redis和生成快照的主数据中心,数据也是安全的。

由于许多Redis用户都处于启动阶段,没有太多预算,我们会介绍一些最有意思的灾难恢复技术,而不用太多的花销。

  • Amazon S3和一些类似的服务是帮助你灾难恢复系统的一个好办法。很简单,只需要将你的每日或每小时的RDB快照以加密的方式传输到S3。你可以使用 gpg -c 来加密你的数据(以对称加密模式)。确保将你的密码保存在不同的安全地方(例如给一份到你的组织中的最重要的人)。推荐使用多个存储服务以提升数据安全。
  • 使用SCP(SSH的组成部分)来传输你的快照到远程服务器。这是一种相当简单和安全的方式:在远离你的位置获得一个小的VPS,安装ssh,生成一个无口令的ssh客户端key,并将其添加到你的VPS上的authorized_keys文件中(译者注:这是SSH互信,在Linux系统中可以使用ssh-keygen命令生成公私钥)。你就可以自动的传输备份文件了,无需输入密码。为了达到更好的效果,最好是至少从不同的提供商那搞两个VPS。

要知道这种系统如果没有正确的处理会很容易失败。至少一定要确保传输完成后验证文件的大小(要匹配你拷贝的文件),如果你使用VPS的话,可以使用 SHA1 数字签名。

你还需要一个独立的告警系统,在某些原因导致传输备份过程失败时告警。 

时间: 2024-09-10 12:51:38

《Redis官方文档》持久化的相关文章

《Redis官方文档》翻译邀请

并发编程网定期组织翻译官方指南,十一月组织翻译Redis官方文档, 官方地址,有兴趣的同学可以通过评论领取,每次领取一节,翻译完后再领取其他章节.如果翻译超过10篇文章,并发网会赠送一本作者签名的<JAVA并发编程的艺术>. 如何交稿?直接在并发网注册账号后点新建文章,参考我要投稿. 介绍 admin.md     (ethfoo领取) benchmarks.md   (looyup已领取) clients.md  (mircle123领取) cluster-spec.md  (carlvin

《Redis官方文档 》sentinel

原文链接 Redis Sentinel 文档 Redis Sentinel为Redis提供了高可用解决方案.实际上这意味着使用Sentinel可以部署一套Redis,在没有人为干预的情况下去应付各种各样的失败事件. Redis Sentinel同时提供了一些其他的功能,例如:监控.通知.并为client提供配置. 下面是Sentinel的功能列表: 监控(Monitoring):Sentinel不断的去检查你的主从实例是否按照预期在工作. 通知(Notification):Sentinel可以通

《Redis官方文档》分区

分区:如何把数据存储到多个Redis实例中 分区就是把你的数据分割到多个Redis实例中的一个过程,因此每个实例仅仅包含部分键.这篇文章第一部分介绍分区概念,第二部分将介绍Redis分区的用法. (译者注:Redis集群是分区事实上标准) 为什么分区是非常有用的 分区在Redis中主要有两个目的: 分区利用多台机器的内存构建一个更大数据库.如果不使用分区,数据库大小受限于单个计算机内存. 分区可以在多核和多计算机之间弹性扩展计算能力,并且分区可以在多计算机和网络适配器之间弹性扩展网络带宽. 分区

《Redis官方文档》Redis集群教程

原文链接 译文链接 译者: tiffany 这篇教程是Redis集群的简要介绍,而非讲解分布式系统的复杂概念.它主要从一个使用者的角度介绍如何搭建.测试和使用Redis集群,至于Redis集群的详细设计将在"Redis集群规范"中进行描述. 本教程以redis使用者的角度,用简单易懂的方式介绍Redis集群的可用性和一致性. 注意: 本教程要求redis3.0或以上的版本. 如果你打算部署redis集群,你可以读一些关于集群的详细设计,当然,这不是必须的.由这篇教程入门,先大概使用一下

《Redis官方文档》使用Redis作为LRU缓存

原文链接  译者:boyhou (WeChat:HouYongBo923) 如果你使用redis作为缓存,当添加新数据时,若有内存大小等限制,系统默认会根据一定的规则自动清理旧数据.这种处理方式在开发社区中众所周知,因为它也是非常流行的缓存系统 memcached 的默认处理方式. LRU(LRU全称是Least Recently Used,即最近最久未使用)实际上只是Redis支持的内存回收策略中的一种.这篇文章将要讲述Redis的 maxmemory 配置选项,该配置选项用来限制 Redis

《Redis官方文档》Redis调试指南

原文链接      译者:Adeline Redis开发过程中十分注重其稳定性:我们尽一切努力来保证每一个版本的稳定,不出现突然崩溃等情况.但是即使在我们百分百的努力下,仍然没办法保证百分百的无bug. Redis出现崩溃时,会生成一个详细的报告来描述当时的情景,但是有时候只看报告还不够,而且Redis的核心开发团队可能也没办法独立重现你出现崩溃时候的场景:在这种情况下,我们需要用户能够重现这个情景来帮助我们. 这个指南讲解了如何使用GDB来获得Redis开发者可能用到的信息. GDB是什么?

《Redis官方文档》用Redis构建分布式锁

原文链接  译者:yy-leo   校对:方腾飞(红体标记重点) 用Redis构建分布式锁 在不同进程需要互斥地访问共享资源时,分布式锁是一种非常有用的技术手段. 有很多三方库和文章描述如何用Redis实现一个分布式锁管理器,但是这些库实现的方式差别很大,而且很多简单的实现其实只需采用稍微增加一点复杂的设计就可以获得更好的可靠性. 这篇文章的目的就是尝试提出一种官方权威的用Redis实现分布式锁管理器的算法,我们把这个算法称为RedLock,我们相信这个算法会比一般的普通方法更加安全可靠.我们也

《Redis官方文档》 FAQ

原文地址 译者:zivyu 为什么Redis与其他的k-v存储相比不一样 有两个主要的原因 redis在键-值数据库中是一个不同的发展方向,值可以包含更复杂的数据类型,同时许多原子操作定义在这些数据类型上.redis的数据类型和基本数据结构密切相关,没有额外的抽象层,同样对于程序员也是直接可见的. redis是一个在内存中但是可以持久化到磁盘上的数据库,所以它代表了一个不同的权衡,高速读写被实现,但是对数据集有限制,那就是不能大于内存的大小.在内存中的数据库还有另外的优点,内存中表示的复杂数据结

《Redis官方文档》 redis 虚拟内存

原文链接 译文链接 译者: youxin2012 重点提示: Redis 的虚拟内存(VM) 目前不被提倡使用,Redis 2.4将是有虚拟内存特性的最新版本(但它同样提示不鼓励使用虚拟内存).我们发现使用虚拟内存会有一些不足和问题.对于Redis的未来,至少目前在不考虑支持比RAM更大的数据库时,我们希望能提供最好的内存数据库(持久化仍然在磁盘上).我们随后的成果将关注提供脚本,集群以及更好的持久化方面. 虚拟内存 Redis 虚拟内存这一特性将首次出现在Redis 2.0的一个稳定发布版中.