揭秘Redis中AOF与RDB的协同作战,确保数据万无一失

本文详细解释了Redis的AOF和RDB两种持久化方式,包括AOF的工作原理、写回策略及其可能带来的风险,以及RDB的内存快照机制。同时探讨了如何通过合理搭配AOF和RDB提高数据可靠性和性能。
摘要由CSDN通过智能技术生成

        众所周知Redis内存数据库,如果发生了宕机,数据就会丢失,那Redis是如何做持久化的呢?Redis有两种持久化方式,分别为AOF和RDB,但是他们二者是如何配合工作的呢?本文将带你了解一下。

AOF持久化

        AOF(Append Only File)日志是通过日志文件进行持久化的方式。通常我们熟悉的数据库(MySQL等)都是写前日志(Write Ahead Log),在实际写数据之前,先将修改的数据写入到日志(redo Log)中,以便故障时进行回复。但是Redis是写后日志,为什么Redis和其他数据库不一样呢?

        传统的数据库中日志中记录的是修改后的数据,而AOF中记录的是一条条具体的命令,如:set key value,这些命令以文件的形式保存。如果先写日志,就有可能记录上错误的命令,为了减少额外的检查开销,Redis采用了先执行命令,执行成功后,才记录AOF日志。这与MySQL等数据库不同,MySQL等数据库等有语法检查,可以避免记录错误的日志。Redis如果先写AOF日志文件的话,会记录很多错误的命令,所以采用了写后日志。

        不过这种方式存在两个风险:

  1. 如果刚执行完命令Redis服务器宕机了,还没来得及记录AOF日志,这就存在数据丢失的风险。
  2. AOF日志虽然避免了当前命令的阻塞,当时日志文件要写入到磁盘,写入磁盘时如果磁盘压力大,会导致后续的写入无法进行。

        写回策略

        对于上面的问题,Redis提供了三种写回策略

  • Always策略:同步写回,每个命令执行完,立马同步的将命令写回磁盘,而且是主线程负责
  • Everysec策略:每秒写回,每个写命令执行完,只是先把日志写到AOF文件的内存缓存区,每隔一秒把缓冲区中的内容写回磁盘
  • NO策略:操作系统控制写回,每个写命令执行完,只是先把日志写到AOF文件缓存区,由操作系统决定何时将缓存区写入磁盘。

        这三种策略无法做到两全其美

        同步模式可以不丢失数据,但是会造成相应的阻塞,影响性能;每秒写回虽然一定程度上提高了性能,但如果发生了宕机,还是会丢失一部分数据;操作系统控制的写回策略,落盘时机已经不掌握在Redis手中,只要没写回磁盘,宕机的话还是会丢失数据。

        需要根据应用场景,在高性能和高可靠性方面来进行权衡,评估最合适的写回策略。

        AOF日志重写

        随着服务的运行,AOF日志是追加写入的,所以写入日志会越来越多,AOF日志文件会越来越大,但是日志中可能会存在对相同key的操作,比如在t1时刻操作如下:set key value1,在t2时刻又操作了相同的key:set key value2,这样的操作多的话会造成AOF日志中存在很多重复的内容,浪费空间,所以需要对AOF进行重写。

        重写的机制是将相同的命令进行合并,有多变一的功能,这样可以将日志文件变小。

        虽然AOF日志重写会减小日志,但是会不会阻塞主线程呢?

        AOF重写会阻塞吗

        和AOF由主线程写回不同,重写是由后台子进程bgrewriteaof来完成的,这时为了避免主线程阻塞,导致性能下降。

        每次执行重写时,主线程fork出后台bgrewriteaof子进程。此时会把主线程会把内存中的数据复制一份给子进程,然后bgrewriteaof就可以在不影响主线程的情况下,逐一把拷贝的数据写入操作,记入重写日志。因为主线程为阻塞,仍然可以处理客户端的请求。如果有写入请求时,Redis会利用操作系统的写时复制(Copy On Write)写入到缓存区,及时宕机了,这个日志仍然齐全,可用于数据恢复。

        关于写时复制(Copy On Write)将在其他文章专门讨论,这里不做详细介绍,欢迎关注查看。

RDB持久化

        由于AOF在数据恢复时是一条条命令执行的,耗时长性能差,RDB(Redis DataBase)内存快照是另一种持久化方式,既可以保证可靠性,还能在宕机时实现快速恢复。所谓快照,就是指内存中的数据在某一时刻的记录。把某一时刻的状态以文件的形式写到磁盘上,也就是快照。

        RDB记录的时某一时刻的数据,而不是对数据的操作,所以在恢复数据时,直接读入RDB文件就能实现快速恢复。但是需要考虑两个问题

  1. 对哪些数据做快照?这直接影响快照效率
  2. 做快照是,数据还能被修改吗?这直接影响是否对主线程造成阻塞

        给哪些数据做快照?

        Redis将数据保存在内存中,如果对内存中的全量数据做快照,在写回到磁盘中,开销较大,而且数据越多,RDB文件越大,写磁盘的开销也就越大。

        Redis单线程模型就决定了,要尽量避免主线程阻塞操作,Redis提供了两种生成RDB的方式:

  • save:由主线程执行,会导致阻塞
  • bgsave:创建一个子进程,专门用于写入RDB文件,避免主线程阻塞,这也是Redis RDB文件生成的默认配置。

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

        快照时数据能修改吗?

        对于内存快照而言,我们当然不希望数据被修改。但是,如果执行快照期间数据不能被修改,是有问题的,在这期间Redis不能处理数据的写操作,那无疑会给业务造成巨大的影响。bgsave不是能避免阻塞吗,避免阻塞和正常处理写操作并不是一回事。此时主线程的确没有阻塞,可以正常接收请求,但为了保证完整性,它只能处理读操作,因为不能修改正在执行快照的数据。

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

        bgsave子进程是由主线程fork生成的,可以共享主线程的所有内存数据。bgsave子进程运行后,开始读取主线程的内存数据,并把它们写入RDB文件。

        关于写时复制(Copy On Write)将在其他文章专门讨论,这里不做详细介绍,欢迎关注查看。

        AOF和RDB配合工作

        对于快照来说,所谓连拍就是指连续地做快照。这样一来,快照的间隔时间变的很短,即使某一时刻发生了宕机,因为这一时刻快照刚执行,丢失的数据也不会太多。但是,这其中的快照间隔时间就很关键了。

        频繁的将全量数据写入磁盘,会给磁盘带来很大压力,多个快照竞争有限的磁盘带宽,前一个快照还没做完,后一个又开始了,容易造成恶性循环。所以RDB频率不好掌握。

        我们可以在两次RDB快照期间用AOF来进行持久化,二者配合使用,这样就提高了可高性,也保证了性能。

        

往期精彩内容推荐

不止内存优势:Redis高性能背后的神秘面纱,超越想象加速秘诀-CSDN博客

Redis缓存危机大揭秘:雪崩、击穿与穿透——从理论到实战防御策略_redis缓存雪崩、穿透以及技术预防-CSDN博客​​​​​​​

Redis 6.0进化之路:关键新特性详解_redis 6.0 特性-CSDN博客

       

  • 34
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

超越不平凡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值