国内最全IT社区平台 联系我们 | 收藏本站
华晨云阿里云优惠2
您当前位置:首页 > 数据库 > 数据库应用 > NoSql之Redis持久化

NoSql之Redis持久化

来源:程序员人生   发布时间:2016-06-24 08:33:17 阅读次数:3041次

       如果你认为Redis是1个key value store, 那可能会用它来代替MySQL;如果认为它是1个可以持久化的cache, 可能只是它保存1些频繁访问的临时数据。

       我们来假想1个问题,通过前面的介绍,我们知道了redis与memcached都可以当作缓存,提高访问效力,那末如果对突然断电或其他故障,那末是否是意味着我们的缓存数据要丢失?

       redis是1个支持持久化的内存数据库,也就是说redis需要常常将内存中的数据同步到磁盘来保证持久化。也就是说缓存和我们的数据库之间有着交互,我们可以把缓存中的数据保存下来这也就是redis比其他缓存强大的地方:持久化。

       redis支持两种持久化方式,1种是 RDB(快照)也是默许方式,另外一种是Append-only file(缩写aof)的方式。
       RDB 持久化可以在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot)。

       AOF 持久化记录服务器履行的所有写操作命令,并在服务器启动时,通太重新履行这些命令来还原数据集。 AOF 文件中的命令全部以 Redis 协议的格式来保存,新命令会被追加到文件的末尾。 Redis 还可以在后台对 AOF 文件进行重写(rewrite),使得 AOF 文件的体积不会超越保存数据集状态所需的实际大小。

       Redis 还可以同时使用 AOF 持久化和 RDB 持久化。 在这类情况下, 当 Redis 重启时, 它会优先使用 AOF 文件来还原数据集, 由于 AOF 文件保存的数据集通常比 RDB 文件所保存的数据集更完全。你乃至可以关闭持久化功能,让数据只在服务器运行时存在。

RDB

       快照是默许的持久化方式。这类方式是就是将内存中数据以快照的方式写入到2进制文件中,默许的文件名为dump.rdb。可以通过配置设置自动做快照持久 化的方式。
       我们可以配置redis在n秒内如果超过m个key被修改就自动做快照,下面是默许的快照保存配置

save 900 1 #900秒内如果超过1个key被修改,则发起快照保存 save 300 10 #300秒内容如超过10个key被修改,则发起快照保存 save 60 10000

RDB 快照运作进程

       在默许情况下, Redis 将数据库快照保存在名字为 dump.rdb 的2进制文件中。你可以对 Redis 进行设置, 让它在“ N 秒内数据集最少有 M 个改动”这1条件被满足时, 自动保存1次数据集。

       你也能够通过调用 SAVE 或 BGSAVE , 手动让 Redis 进行数据集保存操作。比如说, 以下设置会让 Redis 在满足“ 60 秒内有最少有 1000 个键被改动”这1条件时, 自动保存1次数据集:

save 60 1000

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

       Redis 调用 fork() ,同时具有父进程和子进程。

       子进程将数据集写入到1个临时 RDB 文件中。
       当子进程完成对新 RDB 文件的写入时,Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。

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

       只进行追加操作的文件(append-only file,AOF)

AOF

       从 1.1 版本开始, Redis 增加了1种完全耐久的持久化方式: AOF 持久化。
       你可以通过修改配置文件来打开 AOF 功能:

appendonly yes

       从现在开始, 每当 Redis 履行1个改变数据集的命令时(比如 SET), 这个命令就会被追加到 AOF 文件的末尾。

       这样的话, 当 Redis 重新启时, 程序就能够通太重新履行 AOF 文件中的命令来到达重建数据集的目的。

       另外一点需要注意的是,每次快照持久化都是将内存数据完全写入到磁盘1次,其实不 是增量的只同步脏数据。如果数据量大的话,而且写操作比较多,必定会引发大量的磁盘io操作,可能会严重影响性能。

       另外由于快照方式是在1定间隔时间做1次的,所以如果redis意外down掉的话,就会丢失最后1次快照后的所有修改。如果利用要求不能丢失任何修改的话,可以采取aof持久化方式.

AOF运作进程

       aof 比快照方式有更好的持久化性,是由于在使用aof持久化方式时,redis会将每个收到的写命令都通过write函数追加到文件中(默许是 appendonly.aof)。

       当redis重启时会通太重新履行文件中保存的写命令来在内存中重建全部数据库的内容。固然由于os会在内核中缓存 write做的修改,所以可能不是立即写到磁盘上。这样aof方式的持久化也还是有可能会丢失部份修改。

       不过我们可以通过配置文件告知redis我们想要 通过fsync函数强迫os写入到磁盘的时机。有3种方式以下(默许是:每秒fsync1次)

# appendfsync always //每次收到写命令就立即强迫写入磁盘,最慢的,但是保证完全的持久化,不推荐使用
appendfsync everysec //每秒钟强迫写入磁盘1次,在性能和持久化方面做了很好的折衷,推荐
# appendfsync no //完全依赖os,性能最好,持久化没保证

具体进程以下
       1. redis调用fork ,现在有父子两个进程

       2. 子进程根据内存中的数据库快照,往临时文件中写入重建数据库状态的命令

       3.父进程继续处理client要求,除把写命令写入到原来的aof文件中。同时把收到的写命令缓存起来。这样就可以保证如果子进程重写失败的话其实不会出问题。

       4.当子进程把快照内容写入已命令方式写到临时文件中后,子进程发信号通知父进程。然后父进程把缓存的写命令也写入到临时文件。

       5.现在父进程可使用临时文件替换老的aof文件,并重命名,后面收到的写命令也开始往新的aof文件中追加。

       需要注意到是重写aof文件的操作,并没有读取旧的aof文件,而是将全部内存中的数据库内容用命令的方式重写了1个新的aof文件,这点和快照有点类似。

       安装Redis以后,我们会发现redis.conf文件,在这里面我们可以设置以上两种持久化方式。

RDB 的优点

       RDB 是1个非常紧凑(compact)的文件,它保存了 Redis 在某个时间点上的数据集。 这类文件非常合适用于进行备份: 比如说,你可以在最近的 24 小时内,每小时备份1次 RDB 文件,并且在每月的每天,也备份1个 RDB 文件。

        这样的话,即便遇上问题,也能够随时将数据集还原到不同的版本。RDB 非常适用于灾害恢复(disaster recovery):它只有1个文件,并且内容都非常紧凑,可以(在加密后)将它传送到别的数据中心,或亚马逊 S3 中。

       RDB 可以最大化 Redis 的性能:父进程在保存 RDB 文件时唯1要做的就是 fork 出1个子进程,然后这个子进程就会处理接下来的所有保存工作,父进程不必履行任何磁盘 I/O 操作。RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。

RDB 的缺点

       如果你需要尽可能避免在服务器故障时丢失数据,那末 RDB 不合适你。 虽然 Redis 允许你设置不同的保存点(save point)来控制保存 RDB 文件的频率, 但是, 由于RDB 文件需要保存全部数据集的状态, 所以它其实不是1个轻松的操作。 因此你可能会最少 5 分钟才保存1次 RDB 文件。

        在这类情况下, 1旦产生故障停机, 你便可能会丢失好几分钟的数据。每次保存 RDB 的时候,Redis 都要 fork() 出1个子进程,并由子进程来进行实际的持久化工作。

       在数据集比较庞大时, fork() 可能会非常耗时,造成服务器在某某毫秒内停止处理客户端; 如果数据集非常巨大,并且 CPU 时间非常紧张的话,那末这类停止时间乃至可能会长达整整1秒。 虽然 AOF 重写也需要进行 fork() ,但不管 AOF 重写的履行间隔有多长,数据的耐久性都不会有任何损失。

AOF 的优点

       使用 AOF 持久化会让 Redis 变得非常耐久(much more durable):你可以设置不同的 fsync 策略,比如无 fsync ,每秒钟1次 fsync ,或每次履行写入命令时 fsync 。

        AOF 的默许策略为每秒钟 fsync 1次,在这类配置下,Redis 依然可以保持良好的性能,并且就算产生故障停机,也最多只会丢失1秒钟的数据( fsync 会在后台线程履行,所以主线程可以继续努力地处理命令要求)。

       AOF 文件是1个只进行追加操作的日志文件(append only log), 因此对 AOF 文件的写入不需要进行 seek , 即便日志由于某些缘由而包括了未写入完全的命令(比如写入时磁盘已满,写入中途停机,等等), redis-check-aof 工具也能够轻易地修复这类问题。

       Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写: 重写后的新 AOF 文件包括了恢复当前数据集所需的最小命令集合。 全部重写操作是绝对安全的,由于 Redis 在创建新 AOF 文件的进程中,会继续将命令追加到现有的 AOF 文件里面,即便重写进程中产生停机,现有的 AOF 文件也不会丢失。 而1旦新 AOF 文件创建终了,Redis 就会从旧 AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操作。

       AOF 文件有序地保存了对数据库履行的所有写入操作, 这些写入操作以 Redis 协议的格式保存, 因此 AOF 文件的内容非常容易被人读懂, 对文件进行分析(parse)也很轻松。 导出(export) AOF 文件也非常简单: 举个例子, 如果你不谨慎履行了 FLUSHALL 命令, 但只要 AOF 文件未被重写, 那末只要停止服务器, 移除 AOF 文件末尾的 FLUSHALL 命令, 并重启 Redis , 就能够将数据集恢复到 FLUSHALL 履行之前的状态。

AOF 的缺点

       对相同的数据集来讲,AOF 文件的体积通常要大于 RDB 文件的体积。根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB 。

       在1般情况下, 每秒 fsync 的性能仍然非常高, 而关闭 fsync 可让 AOF 的速度和 RDB 1样快, 即便在高负荷之下也是如此。 不过在处理巨大的写入载入时,RDB 可以提供更有保证的最大延迟时间(latency)。

       AOF 在过去曾产生过这样的 bug : 由于个别命令的缘由,致使 AOF 文件在重新载入时,没法将数据集恢复成保存时的原样。 (举个例子,阻塞命令 BRPOPLPUSH 就曾引发过这样的 bug 。) 测试套件里为这类情况添加了测试: 它们会自动生成随机的、复杂的数据集, 并通太重新载入这些数据来确保1切正常。 虽然这类 bug 在 AOF 文件中其实不常见, 但是对照来讲, RDB 几近是不可能出现这类 bug 的。

RDB 和 AOF ,我应当用哪个?

       1般来讲,如果想到达足以媲美 PostgreSQL 的数据安全性, 你应当同时使用两种持久化功能。如果你非常关心你的数据,但依然可以承受数分钟之内的数据丢失, 那末你可以只使用 RDB 持久化。有很多用户都只使用 AOF 持久化, 但我们其实不推荐这类方式: 由于定时生成 RDB 快照(snapshot)非常便于进行数据库备份, 并且 RDB 恢复数据集的速度也要比 AOF 恢复的速度要快, 除此以外, 使用 RDB 还可以免之条件到的 AOF 程序的 bug 。

生活不易,码农辛苦
如果您觉得本网站对您的学习有所帮助,可以手机扫描二维码进行捐赠
程序员人生
------分隔线----------------------------
分享到:
------分隔线----------------------------
关闭
程序员人生