三、Redis 的持久化技术 —— AOF 日志 与 RDB快照

考虑这样一个场景,当Redis发生异常重启时,Redis 的数据都是存在内存中的,这时该怎么找回来?
实际上,Redis 的持久化主要有两大机制实现 —— AOF日志 和 RDB快照。

AOF日志

AOF日志如何实现的

AOF日志是 Redis 执行命令后,把数据写入内存,然后记录下这条命令到AOF日志中。
先写数据,再写日志,这样可以避免额外的命令语法检查开销,并且不会阻塞当前的写操作。

但是这样,也会有潜在风险:
如果在写完数据后,还没来得及写日志,Redis 就宕机了,那么这条命令就没有记录到 AOF 日志中。
其次,虽然先写数据再记日志,不会阻塞当前的请求。但是写AOF日志,也是在主线程中执行的,并且是写入磁盘,依然会阻塞下一个请求。

AOF在何时写入磁盘

既然 AOF 在写入磁盘,会导致阻塞当前线程。那么,如何降低阻塞的风险呢?
实际上,AOF 的配置项 appendfsync 控制了 AOF 日志写回磁盘的时机,它有三个可选项:

  • Always,同步写回。就是每个写命令执行完后,马上将日志写回磁盘。
  • Everysec,每秒写回。每个写命令执行完后,把 AOF日志写入内存缓冲区,然后每秒把缓冲区内容写道磁盘一次。
  • No,操作系统控制写回。每个写命令执行完后,把命令写到内存缓冲区,由操作系统决定何时写回磁盘。

以上三种AOF日志写回磁盘的时机,都各有利弊。如果写回操作频繁,可以降低 Redis 宕机后,数据丢失的风险,但是会导致 Redis 的线程阻塞,执行效率变低。相反,如果写回操作频率低,可以提高 Redis 的执行效率,但是一旦宕机,未来得及写入磁盘的 AOF 日志对应的写命令数据就会丢失。

实际上,Redis 的 AOF日志,通常都是根据实际业务场景决定何时写回磁盘的。 这就是一种性能和可靠性的取舍。

AOF 日志重写
虽然写命令的增加, AOF 日志会不断增大,当 AOF 日志大到一定程度时,就会导致性能降低的问题。甚至,可能导致 AOF 日志将磁盘占满了。另外,当 AOF 日志太大时,Redis 宕机后,根据 AOF 恢复数据,整个恢复过程会非常缓慢。

这时候, AOF重写机制就派上了用场。

AOF 日志记录的是写操作,每接受到一条写命令,就把这条命令追加写入 AOF 文件。 这时,如果一个 key,对应的 value 值被反复修改,其实,对应的有意义的数据,应该是最新的数据,过去的修改记录并不重要了。所以,AOF 重写机制,会根据这个 key 当前的最新状态,生成对应的写入命令,并写入 AOF重写文件。这样一来,这个 键值对 在 AOF 日志中只占用了一条命令。 并且,恢复数据时,只根据这条命令,就可以完成这个键值对的数据恢复。
在生成了 AOF重写文件后,用它替换当前的 AOF 文件,就完成了 AOF 文件的压缩。

现在知道了AOF的重写机制后,需要思考这样一个问题:AOF重写后,日志会变小,但是要把这个 Redis 的最新数据对应的操作日志都写回磁盘,依然会很耗时,这又怎么办呢?

实际上,与AOF日志正常写入流程不同,AOF重写不是由主线程完成的,而是由子进程 bgrewriteaof 完成的。

AOF 重写的过程可以总结为 “一个拷贝,两份日志”

一个拷贝:AOF重写,Redis 的主线 fork 出子进程 bgrewriteaof,将主线程的内存拷贝一份给子进程,然后 子进程 再把拷贝过来的数据,写成操作日志,记入 AOF 重写日志。

两份日志:主线程 fork 出子进程后,依旧可以正常处理新过来的请求,如果在此时,有新的写命令,这条写命令会计入到两个日志中。
在主线程中,会将这个写命令写入 AOF 缓冲区中,在执行 AOF 磁盘写回时,将此命令从 AOF 缓冲区中取出写入磁盘。 另外,这个操作也会被写入到 AOF 重写缓冲区,等子进程所有的拷贝数据都生成写命令并写入了 AOF 重写日志后,在 AOF 的重写缓冲区也会写入 AOF 重写文件。这样,就能保证在生成 AOF 重写文件过程中,新产生的 写命令被遗漏。

AOF日志总结:
1、AOF 是指每条写命令执行后,将此命令写入 AOF 文件,以实现 Redis 重启能通过执行 AOF 文件中的命令恢复数据。
2、写 AOF日志是在主线程中执行的,为了降低主线程阻塞情况,AOF 日志会写入 AOF缓冲区,有三种不同的模式控制何时将 AOF 缓冲区内容写回磁盘。
3、AOF 日志过大时,有 AOF 重写机制来压缩 AOF 日志。 AOF 重写是由 主线程 fork 的子进程完成的,不会阻塞当前主线程。并且,有 “一处拷贝,两处日志”的机制保证在 AOF 重写过程中,新产生的 写命令 不会被遗漏。 AOF重写完成后,由AOF重写日志替代当前 AOF 日志。

RDB 快照

上面提到的 AOF 日志实现持久化,是指当 Redis 宕机重启时,可以通过执行 AOF 日志中的命令实现数据恢复。 然而,如果 AOF 日志很大时,Redis 恢复数据就会很慢。 那有没有另外一种持久化的技术,能实现 Redis 的快速恢复数据呢?

RDB 快照就能实现快速恢复。 RDB 快照就是把某一时刻的 Redis 数据,以文件的形式写到磁盘中,实现数据持久化。 然后在 Redis 异常重启时,将 RDB 文件直接读入内存,就能实现数据恢复。

这种RDB快照数据恢复的方式,当然比根据 AOF日志 恢复数据要快。但是这里依然要考虑两个问题:
1、生成 RDB 文件,需要对 Redis 的全量数据进行备份,这会导致 Redis 主线程的阻塞吗?
2、何时生成 RDB 文件?

通过 bgsave 子进程,非阻塞式的生成 RDB 文件
我们可以根据 bgsave 命令,创建子进程,从而在不阻塞主线程的情况下生成 RDB 文件。

生成 RDB 文件时,主线程能执行写命令吗?
在生成 RDB 文件时,如果主线程进行了写操作,修改了正在执行快照的数据,导致了数据的不一致怎么办呢?
实际上,Redis 借助了操作系统提供的写时复制技术(Copy-On-Write),在执行快照时,如果 Redis 需要对某份数据进行写操作,会生成这个数据的副本,然后,主线程在这个副本上进行修改,bgsave子进程写入的依然是原来的数据。然后,在快照结束后,再将此副本覆盖原本的数据。

何时生成 RDB 文件
在考虑何时生成 RDB 文件时,很自然地考虑到,如果写 RDB 文件频率高,那么会降低 Redis 的执行效率(写磁盘会带来额外开销,并且 fork 子进程也会阻塞当前主线程)。但是如果写 RDB 文件频率低,会导致 Redis 宕机恢复时,某些数据的丢失。

这里,可以通过增量快照的方式,降低快照导致的额外开销。 增量快照,顾名思义,就是在做完第一次全量快照以后,后面再进行快照时,只对修改了的数据快进行快照记录即可。

但是,增量快照也会带来其他问题。Redis 需要记住,哪些数据进行了修改,并且需要额外的空间去记录这些被修改的数据。

RDB 快照结合 AOF 日志 实现Redis 数据恢复

AOF 日志恢复数据耗时长,而 RDB 快照不好控制快照频率。其实,可以通过两者结合的方式,来实现 Redis 的数据恢复。

在进行 RDB 全量快照以后,通过 AOF 日志记录后面进行的写操作。然后,在下一次 RDB 全量快照时,清空 AOF 日志,重新记录这次 RDB 快照后产生的写操作。
在恢复 Redis 的数据时,只需要读取最新的RDB日志到内存中,再根据执行 AOF 日志的命令,恢复快照后产生的数据修改,就能恢复完整的数据。

这样一来,RDB 快照的频率不需要太高,AOF 日志也不会记得特别长。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容