美文网首页
自我系统学习Redis小记-02

自我系统学习Redis小记-02

作者: Timor小先生 | 来源:发表于2021-10-19 19:23 被阅读0次

04 | AOF日志:宕机了,Redis如何避免数据丢失?

1、一个问题引出持久化:一旦服务器宕机,内存中的数据将全部丢失。

容易的解决方案:从后端数据库恢复这些数据,存在两个问题

1)、频繁操作数据库,给db带来压力

2)、一段时间内导致应用程序变慢

所以,redis持久化至关重要,能避免从后端恢复数据,目前redis有两种持久化方式,即 AOF 日志和 RDB 快照

2、AOF 日志是如何实现的

DB是WAL,写前日志,也就是在写数据前,先把修改的数据记录在日志中,以便故障恢复

AOF是写后日志,意思是Redis是先执行命令,把数据写入内存,再记录日志

Redis AOF操作过程

AOF 为什么要先执行命令再记日志呢?

不同于DB,AOF记录的是每一条命令,以文本方式保存

AOF 日志内容

*3 :代表有三部分,每部分都是由“$+数字”开头,后面紧跟着具体的命令、键或值,“数字”代表和部分有多少字节

Redis再向AOF记录日志时不会检查命令的语法,因此如果先记日志在执行命令可能出现错误的命令,导致redis日志恢复时出错。

所以写后日志的好处是:

1)、先让系统执行命令,只有命令能执行成功,才会被记录到日志中,可以避免出现记录错误命令的情况

2)、不会阻塞当前的写操作

AOF 也有两个潜在的风险

1)、如果执行完一条命令直接宕机,没来得及记录日志,那么这个命令和相应的数据就有丢失的风险

2)、AOF 虽然避免了对当前命令的阻塞,但可能会给下一个操作带来阻塞风险

这是因为,AOF 日志也是在主线程中执行的,如果在把日志文件写入磁盘时,磁盘写压力大,就会导致写盘很慢,进而导致后续的操作也无法执行了。

所以,AOF写会磁盘的时机很重要。

3、三种写回策略-----AOF配置项 appendfsync 的三个可选值。

Always,同步写回:每个写命令执行完,立马同步地将日志写回磁盘;

Everysec,每秒写回:每个写命令执行完,只是先把日志写到 AOF 文件的内存缓冲区,每隔一秒把缓冲区中的内容写入磁盘;

No,操作系统控制的写回:每个写命令执行完,只是先把日志写到 AOF 文件的内存缓冲区,由操作系统决定何时将缓冲区内容写回磁盘。

三种写回策略优缺点

4、AOF日志文件太大了怎么办?

日志过大带来的三个影响:

1)、文件系统本身限制文件大小,过大无法保存

2)、文件过大,再往里面追加命令,效率变慢

3)、如果发生宕机,AOF中记录的命令熬一个一个的被执行,用于故障恢复,如果日志文件过大,整个恢复过程会相当缓慢,会影响Redis的正常使用

解决方案:AOF 重写机制

说白了就是多条命令变一条命令,下面这个是6变1

AOF重写减小日志大小

5、AOF重写会阻塞吗?

和 AOF 日志由主线程写回不同,重写过程是由后台线程 bgrewriteaof 来完成的,这也是为了避免阻塞主线程,导致数据库性能下降。

即:一个拷贝,两处日志:

一个拷贝:每次执行重写时,主线程 fork 出后台的 bgrewriteaof 子进程。此时,fork 会把主线程的内存拷贝一份给 bgrewriteaof 子进程,这里面就包含了数据库的最新数据。然后,bgrewriteaof 子进程就可以在不影响主线程的情况下,逐一把拷贝的数据写成操作,记入重写日志。

两处日志:因主线程未阻塞,仍然可以执行写操作,此时,如有写操作,

第一处日志指正在使用的 AOF 日志,Redis会把这个操作写到他的缓冲区,这样一来即使宕机,这个aof日志是齐全的,可以用来恢复;

第二处日志是指新的 AOF 重写日志,这个新的操作也会被记录到重写日志的缓冲区,保证重写aof日志不丢失新的操作,等到拷贝数据的所有操作记录重写完成后,重写日志记录的这些最新操作也会写入新的 AOF 文件,以保证数据库最新状态的记录。此时,我们就可以用新的 AOF 文件替代旧文件了。

AOF非阻塞的重写过程

总结来说,每次AOF重写,Redis会执行一个内存拷贝,用于重写;然后,使用两个日志保证在重写的过程中,新写入的数据不会丢失。而且,因为Redis采用的额外线程完成数据重写,所以整个过程不会阻塞主线程。

6、小结

1)、写回策略三种,trade-off 取舍原则,性能-可靠性

2)、重写日志


05丨内存快照:宕机后,Redis如何实现快速恢复?

1、引出问题,AOF恢复比较缓慢,还有没有既可以保证可靠性,还能在宕机时实现快速恢复的其他方法?

另一种持久化方式:RDB内存快照------所谓内存快照,就是指内存中的数据在某一个时刻的状态记录。这就类似于照片,当你给朋友拍照时,一张照片就能把朋友一瞬间的形象完全记下来。

对 Redis 来说,它实现类似照片记录效果的方式,就是把某一时刻的状态以文件的形式写到磁盘上,也就是快照。

和 AOF 相比,RDB 记录的是某一时刻的数据,并不是操作,所以,在做数据恢复时,我们可以直接把 RDB 文件读入内存,很快地完成恢复。

需要考虑的问题:

1)、对哪些数据做快照?这关系到执行效率

2)、做快照时,数据还能被增删改吗?这关系到 Redis 是否被阻塞,能否同时正常处理请求。

(答案:Redis 会使用 bgsave 对当前内存中的所有数据做快照,这个操作是子进程在后台完成的,这就允许主线程同时可以修改数据。)

2、给哪些内存数据做快照?

Redis提供所有数据的可靠性保证,所以他执行的是全量快照,即将内存中的所有数据都记录到磁盘中。

Redis 提供了两个命令来生成 RDB 文件,分别是 save 和 bgsave。

----------save:在主线程中执行,会导致阻塞;

----------bgsave:创建一个子进程,专门用于写入 RDB 文件,避免了主线程的阻塞,这也是Redis RDB 文件生成的默认配置。

这时就可以通过 bgsave 命令来执行全量快照,这既提供了数据的可靠性保证,也避免了对 Redis 的性能影响。

3、快照时数据能修改吗?

如果在快照时数据修改,会有潜在风险,如果不允许修改,会给业务造成压力。

bgsave 避免阻塞,避免阻塞和正常处理写操作并不是一回事,快照时,主线程能正常接收请求,但是为了保证快照的完整性,他只能处理读操作,不能处理正在快照数据的写操作。

为了快照暂停写操作是不可取的,所以Redis借助操作系统提供写时复制技术(Copy-On-Write, COW),在执行快照时,正常处理写操作。

写时复制机制保证快照期间数据可修改

bgsave 子进程是由主线程 fork 生成的,可以共享主线程的所有内存数据。

bgsave 子进程运行后,开始读取主线程的内存数据,并把它们写入 RDB 文件。读操作主线程、副本线程互不影响。

但是,如果主线程要修改一块数据(例如图中的键值对 C),那么,这块数据就会被复制一份,生成该数据的副本。

然后,bgsave 子进程会把这个副本数据写入 RDB 文件,而在这个过程中,主线程仍然可以直接修改原来的数据。

写时复制技术(Copy-On-Write, COW)就保证里快照完整性、也允许主线程对数据修改,避免对业务影响。

4、可以每秒做一次快照吗?

快照机制下丢失数据

虽然 bgsave 执行时不阻塞主线程,但是,如果频繁地执行全量快照,也会带来两方面的开销

1)、频繁将全量数据写入磁盘,会给磁盘带来很大压力,多个快照竞争有限的磁盘带宽,前一个快照还没做完,后一个又开始了,容易恶性循环。

2)、bgsave 子进程需要通过 fork 操作从主线程创建出来,创建以后不影响主线程,fork 这个创建过程本身会阻塞主线程,而且主线程的内存越大,阻塞时间越长,频繁fork出bgsave子进程,就会频繁阻塞主线程。

解决这个问题可以采用增量快照,也就是说,在做一次全量快照以后,后续的快照只对修改的数据进行快照记录,这样可以避免每次全量快照的开销。

增量快照的前提是:我们需要记住哪些数据被修改了

增量快照示意图

5、混合使用 AOF 日志和内存快照

虽然跟 AOF 相比,快照的恢复速度快,但是,快照的频率不好把握,如果频率太低,两次快照间一旦宕机,就可能有比较多的数据丢失。如果频率太高,又会产生额外开销。

划重点!!!!!

那么,还有什么方法既能利用 RDB 的快速恢复,又能以较小的开销做到尽量少丢数据呢?

Redis 4.0 中提出了一个混合使用 AOF 日志和内存快照的方法。简单来说,内存快照以一定的频率执行,在两次快照之间,使用 AOF 日志记录这期间的所有命令操作。

优点是  :

1)、快照不用频繁执行,避免了频繁 fork 对主线程的影响

2)、两次快照间的操作记录 AOF 日志,不会出现文件过大的情况,也可以避免重写开销

接下来,看一下这个混合模式的过程:

RDB和AOF混合使用

这个混合模式即享受到了RDB的快速恢复,又能享受到AOF记录简单命令。

6、小结

这节课,我们学习了 Redis 用于避免数据丢失的内存快照方法。这个方法的优势在于,可以快速恢复数据库,也就是只需要把 RDB 文件直接读入内存,这就避免了 AOF 需要顺序、逐一重新执行操作命令带来的低效性能问题。

不过,内存快照也有它的局限性。它拍的是一张内存的“大合影”,不可避免地会耗时耗力。虽然,Redis 设计了 bgsave 和写时复制方式,尽可能减少了内存快照对正常读写的影响,但是,频繁快照仍然是不太能接受的。而混合使用 RDB 和 AOF,正好可以取两者之长,避两者之短,以较小的性能开销保证数据可靠性和性能。

最后,关于 AOF 和 RDB 的选择问题,我想再给你提三点建议:

1)、数据不能丢失时,内存快照和 AOF 的混合使用是一个很好的选择;

2)、如果允许分钟级别的数据丢失,可以只使用 RDB;

3)、如果只用 AOF,优先使用 everysec 的配置选项,因为它在可靠性和性能之间取了一个平衡。

相关文章

  • 自我系统学习Redis小记-02

    04 | AOF日志:宕机了,Redis如何避免数据丢失? 1、一个问题引出持久化:一旦服务器宕机,内存中的数据将...

  • 自我系统学习Redis小记-03

    06 | 数据同步:主从库如何实现数据一致? 1、Redis 具有高可靠性,具体是指? 1)、数据少丢失。 AOF...

  • 自我系统学习Redis小记-01

    00 | 开篇词 | 这样学Redis,才能技高一筹 1、思考 为了保证数据的可靠性,Redis 需要在磁盘上读写...

  • 自我系统学习Redis小记-05

    11 | “万金油”的String,为什么不好用了? 1、String 类型的内存空间消耗问题,以及选择节省内存开...

  • 自我系统学习Redis小记-04

    08 | 哨兵集群:哨兵挂了,主从库还能切换吗? 1、引言 哨兵机制,它可以实现主从库的自动切换。通过部署多个实例...

  • 自我系统学习Redis小记-08

    18 | 波动的响应延迟:如何应对变慢的Redis?(上) 1、前言 Redis 突然变慢,不仅影响用户体验,而且...

  • 自我系统学习Redis小记-06

    14 | 如何在Redis中保存时间序列数据? 1、背景 记录用户在网站或者 App 上的点击行为数据,来分析用户...

  • 自我系统学习Redis小记-07

    16 | 异步机制:如何避免单线程模型的阻塞? 1、前言 影响 Redis 性能的 5 大方面的潜在因素 Redi...

  • 自我系统学习Redis小记-09

    20 | 删除数据后,为什么内存占用率还是很高? 1、前言 这样一个问题:明明做了数据删除,数据量已经不大了,为什...

  • 超级努力001:Salim 的20条人生准则 Beta1.0

    总则:有限的生命活出更多的不可能 一、学习 01、自我负责,自我指示,自我检点 02、系统性思考:避免单一纬度看待...

网友评论

      本文标题:自我系统学习Redis小记-02

      本文链接:https://www.haomeiwen.com/subject/ypuaoltx.html