Redis核心技术及实战(四、五 . AOF日志、RDB日志)

四:AOF日志

原文:《04丨AOF日志:宕机了,Redis如何避免数据丢失?》

AOF日志记录了什么? => 操作的具体逻辑,具体格式见下图。

image-20220511213538734

不同于redo log的WAL(写前日志),AOF日志是写后日志,先把数据写到内存中去,再写日志。为什么呢?因为为了避免额外的开销,Redis在向AOF里面记录日志的时候并不会对其进行语法检查,如果先记录日志再执行命令的话,如果语句有错,日志中就记录了错误的命令。除此之外,写后日志不会阻塞当前的写进程

但是AOF也存在两个风险:

  • 如果记录完日志还没有来得及持久化,就宕机了,那么数据就丢失了;
  • 写后日志不会阻塞当前线程,但是可能会阻塞下一个线程。

要想解决这两个问题,就要考虑AOF日志的写盘时机,Redis下面有三种策略,我们根据需求来进行选择。

image-20220511214229918

除此之外,AOF还有一个问题,那就是AOF文件过大会带来三个”性能“问题:文件系统本身对文件的大小有限制、文件太大时追加记录会变慢、发生宕机后恢复数据会很慢。 => AOF重写机制

**AOF重写机制:**把多条命令重写为一条,比如set key a, set key b, set key c => set key c, 只记录最终数据即可。而且,重写日志和AOF日志由主线程写回不同,重写过程是由后台线程bgrewriteaof来完成的,不会阻塞主线程。重写过程可以总结为”一个拷贝,两处日志“:

  • 一个拷贝:每次重写时,主线程都会fork出后台的bgrewriteaof子进程,同时也会把主线程的内存拷贝一份给子进程,然后,bgrewriteaof子进程就可以在不影响主线程的情况下,逐一把拷贝的数据写成操作,记入重写日志中;
  • 两处日志:
    • 第一处日志:主线程并未阻塞,此时新来的操作仍会写到主线程的AOF日志中去
    • 第二处日志:是子进程的AOF重写日志,新来的操作也会写到这个AOF重写日志中;等到拷贝的数据都写完之后,这个AOF重写日志就会替代第一处的主线程日志了。

AOF重写过程中有没有其它潜在的阻塞风险?

  • 风险一:Redis主线程fork创建bgrewriteaof子进程时,内核需要创建用于管理子进程的PCB,然后需要把主线程的PCB内容拷贝给子进程,这个创建和拷贝的过程是在内核中执行的,会阻塞主线程,而且,子进程要拷贝父进程的页表,这个过程也和Redis实例内存有关,如果实例内存越大,fork时间就越长;
  • 风险二:bgrewriteaof子进程会和主线程共享内存,当主线程收到写操作时,会申请新的内存空间来进行操作,如果这个数据是bigkey,数据量比较大,就可能会因为申请大空间而造成阻塞,因为操作系统在分配内存时有查找和锁的开销,会导致阻塞。

总结:

​ AOF日志:逐一记录操作命令(写日志快),在恢复时再逐一执行命令;

​ 其性能受写盘时机影响,三个写盘时机always、everysec、no,我们根据需求来选择;

​ 为避免AOF日志过大而影响性能,有AOF重写机制,由后台线程bgrewriteaof执行,不会阻塞主线程。

​ 但是,AOF恢复数据时太慢了!需要一条一条执行命令。

五:RDB日志

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

RDB方式,也即内存快照,把某一时刻的所有数据状态以文件的形式写到磁盘上。

1. 给哪些数据做快照?全量快照,所有数据。那么它会阻塞主线程吗?RDB文件生成的两种方式:

  • save:在主线程中执行,会导致阻塞;
  • **bgsave:**创建一个子进程,专门用于写入RDB文件,不会阻塞主线程。(默认)

2. 快照时数据能修改吗?

(Note:避免阻塞和正常处理写操作不是一回事!不阻塞可以执行读操作!)

肯定不能为了写操作而暂停快照,那么,这时有写操作怎么办? => **COW(CopyOnWrite)技术:**读操作不影响,写操作时,如果主线程要修改一块数据,那么这块儿数据就会被复制一份,生成该数据的副本(未被修改的吗?),bgsave子进程把该副本数据读入RDB文件中,而在这个过程中,主线程仍然可以对原数据正常进行写操作。

3. 多久做一次快照?

频繁的快照会带来两方面的开销:

  • 磁盘压力大
  • 但是fork创建子进程会阻塞主线程,频繁的fork会严重阻塞主线程

如果两次快照之间的数据变化量不大 => 增量快照

增量快照:做了一次全量快照之后,后续的快照只对修改的数据进行记录即可,这么做的前提是“我们需要记住哪些数据修改了”,而如果数据变化量大的话,这些因为需要记录而产生的额外空间就会很大,就得不偿失了。

4. 混合使用AOF日志和RDB日志的方法!

AOF恢复数据速度太慢,RDB虽然恢复数据快,但是快照的频率不好把握,频率太低可能会丢失太多数据,fork频率太高又会阻塞主线程。

Redis 4.0提出了一种**混合使用AOF日志和RDB日志的方法:RDB以一定的频率执行,在两次RDB之间,使用AOF记录这期间的所有命令操作。**这样一来,快照就不用频繁的执行,避免了频繁fork对主线程的影响,而且AOF也只用记录两次快照之间的操作,不需要记录所有的操作,不会出现文件过大,避免了重写开销。

image-20220511225001449

5. 持久化方法选择的建议:

  • 数据不能丢失时,RDB和AOF混合使用;
  • 允许分钟级别的数据丢失,可以只使用RDB;
  • 如果只用AOF,建议使用everysec,因为它在可靠性和性能之间取了一个平衡。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值