原文链接 译者: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 数字签名。

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

原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: 《Redis官方文档》持久化

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

  1. StackExchange.Redis 官方文档(六) PipelinesMultiplexers

    原文:StackExchange.Redis 官方文档(六) PipelinesMultiplexers 流水线和复用 糟糕的时间浪费.现代的计算机以惊人的速度产生大量的数据,而且高速网络通道(通常在 ...

  2. StackExchange.Redis 官方文档(五) Keys, Values and Channels

    原文:StackExchange.Redis 官方文档(五) Keys, Values and Channels Keys, Values and Channels 在使用redis的过程中,要注意到 ...

  3. StackExchange.Redis 官方文档

    原文:StackExchange.Redis 官方文档 时隔多年的翻译终于完成了第六个,也是很重要的的官方文档,是介绍有关链接管理,管道流水线和多路复用的 官方地址在这里:官方文档 下面做个汇总: S ...

  4. Redis官方文档资源

    官方文档: 如果要深入研究时,官方提供的文档是最权威的. 英文: https://redis.io/documentation 中文: http://www.redis.cn/documentatio ...

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

    用Redis构建分布式锁 在不同进程需要互斥地访问共享资源时,分布式锁是一种非常有用的技术手段. 有很多三方库和文章描述如何用Redis实现一个分布式锁管理器,但是这些库实现的方式差别很大,而且很多简 ...

  6. StackExchange.Redis 官方文档(一) Basics

    基本使用方法: StackExchange.Redis的核心是 StackExchange.Redis 命名空间的 ConnectionMultiplexer 类;它隐藏了多服务器的实现细节.Conn ...

  7. StackExchange.Redis 官方文档(四) KeysScan

    KEYS, SCAN, FLUSHDB 方法在哪? 经常有人问这些问题: 好像并没有看到 Keys(...) 或者 Scan(...)方法?那我要怎么查询数据库里面存有哪些key? 或者 好像没有Fl ...

  8. StackExchange.Redis 官方文档(三) Events

    事件 ConnectionMultiplexer类型提供了很多可以用来了解表面状态下正在发生着什么的事件.这对日志是很有用的. ConfigurationChanged - ConnectionMul ...

  9. StackExchange.Redis 官方文档(二) Configuration

    配置 有多种方式可以配置redis,StackExchange.Redis提供了一个丰富的配置模型,在执行Connect (or ConnectAsync) 时被调用: var conn = Conn ...

随机推荐

  1. Git fetch和git pull的区别, 解决Git报错:error: You have not concluded your merge (MERGE_HEAD exists).

    Git fetch和git pull的区别, 解决Git报错:error: You have not concluded your merge (MERGE_HEAD exists). Git fet ...

  2. LeetCode第[26]题(Java):Remove Duplicates from Sorted Array 标签:Array

    题目难度:Easy 题目: Given a sorted array, remove the duplicates in-place such that each element appear onl ...

  3. mybatis报错 Error instantiating interface com.atguigu.mybatis.dao.DepartmentMapper with invalid types () or values ()

    mybatis报错 Error instantiating interface com.atguigu.mybatis.dao.DepartmentMapper with invalid types ...

  4. IIS注册.NET

    IIS中ASP.NET的版本号此时可选的有1.1.2.0和4.0三个,如果想让IIS把3个版本都集成上,那NET Framework 3种都要安装,默认安装到的是C 盘. IIS注册方式如下:1.1: ...

  5. IOS-支付宝

      一.使用支付宝进行一个完整的支付功能,大致有以下步骤: 与支付宝签约,获得商户ID(partner)和账号ID(seller) 下载相应的公钥私钥文件(加密签名用) 下载支付宝SDK 生成订单信息 ...

  6. Fiddler工作原理与代理设置

    1,什么是Fiddler Fiddler是一个http协议调试代理工具,它能够记录客户端和服务器之间的所有 HTTP请求,可以针对特定的HTTP请求,分析请求数据.设置断点.调试web应用.修改请求的 ...

  7. 理解字符串 Boyer-Moore 算法

    作者: 阮一峰 上一篇介绍了 kmp算法 但是,它并不是效率最高的算法,实际采用并不多. 各种文本编辑器的"查找"功能(Ctrl+F),大多采用Boyer-Moore算法. Boy ...

  8. Arcgis for javascript不同的状态下自定义鼠标样式

    俗话说:爱美之心,人皆有之.是的,没错,即使我只是一个做地图的,我也希望自己的地图看起来好看一点.在本文,给大家讲讲在Arcgis for javascript下如何自定义鼠标样式. 首先,说几个状态 ...

  9. Could not publish to the server.Please assign JRE to the server

    1.错误描述 2.错误原因 由错误提示可知,是Tomcat未绑定JRE,导致报错 3.解决办法 (1)删除新建Tomcat (2)重新新建一个Tomcat,配置好Tomcat路径和JRE路径

  10. windows 下多线程

    unsigned uiThread2ID; HANDLE handle = (HANDLE)_beginthreadex(NULL, , ThreadUploadFun, NULL, CREATE_S ...