Redis中的AOF持久化、重写阻塞、fork阻塞

Redis虽然是基于内存的键值对数据库,但是它同时也支持持久化,可以根据自己的业务来判断是否可以当作数据持久化的数据库使用。
Redis支持两种持久化文件:

  • RDB:记录数据某一时刻的快照;
  • AOF:更新命令以追加的方式写入文件。

AOF怎么记录的

AOF是写后日志,意思是先写内存在记日志。

AOF记录了什么

Redis中的AOF记录了执行的命令,这些命令就保存在文件中。Redis在记录AOF文件时,是不会去判断语法正不正确,所以采用了先写内存后记日志的操作,因为内存竟然写成功了,那么语法必然正确,就没必要去判断语法。如果是采用先记日志在执行命令的话,有可能这个命令是一个错误的命令就会导致记录的日志文件发生错误,导致Redis无法正常运行。
还有一个好处就是,它是在命令执行结束后才会记录日志,所以不会阻塞当前的写操作。

AOF的潜在风险

数据丢失

如果刚刚执行完命令还没来的及写日志文件,Redis就宕机了,这条数据就会有丢失的风险。如果单单时把Redis当作缓存使用的话,这些数据还是可以从后端数据库获取,但是如果是把Redis当作数据库的话,这条数据就有可能存在丢失的可能。

阻塞

AOF也是主线程执行的,如果再把日志文件写入磁盘时,磁盘压力一大,就会导致写磁盘很慢,就会应发后面的操作会阻塞。

为了解决这些问题,Redis提供了三种写回策略,可以根据业务自行配合。

写回策略

写回策略分为三种,可以通过配置appendsync的三个可选值:

  • AOF_FSYNC_NO:同步写回,每次执行写命令后立即同步讲日志写回磁盘;
  • AOF_FSYNC_EVERYSEC:每秒写回,每次执行玩写命令后,先将日志写到AOF文件的缓冲区,没隔一秒把缓冲区的内容写回磁盘;
  • AOF_FSYNC_NO:每个写命令执行完,把日志文件写到AOF文件缓冲区,由操作系统决定什么时候写回磁盘。

就算是有了这三种写回策略,也无法做到十全十美的效果。

  • 同步写回,它虽然保证了数据不会大量丢失,但是每次都写磁盘的代价会很大,现在的计算机都是再规避IO的操作。
  • 每秒写回虽然避免了以上的同步写回的磁盘操作,但是一旦再某一秒Redis宕机了,上一秒的数据就丢失了
  • 操作系统写回的话,这个主动权就不再Redis的手中了,一旦出现什么问题,数据也是有可能丢失的。

AOF的重写机制

随着命令不断从AOF缓存中写入到AOF文件中,AOF文件会越来越大,为了解决这个问题,Redis引入了AOF重写机制来压缩AOF文件。

  • 同一个key的多次写入只保留最后一个命令
  • 已删除、已过期的key的写命令不再保留

归根结底就是去掉重复的命令,因为一个key可能会执行多次,多次就产生重复的命令。

虽然文件缩小了,但是如果Redis有很大的数据量的话,重写的时候还是要考虑会不会阻塞。

AOF重写如何避免阻塞

为了避免阻塞,Redis采用了父子进程来完成重写操作,可以通过命令bgrewriteaof来完成。

每次执行重写命令时会有一次复制,和两个日志文件(旧日志文件,和新复制出的日志文件)。

Redis会使用到操作系统提供的fork()方法创建子进程来完成复制(不是真正的复制物理,而是虚实映射关系,子进程复制了父进程的页表,也能共享父进程的内存数据,就想拥有了父进程的所有数据一样)操作。

子进程再不影响主进程的情况下把数据进行复制重写。

fork子进程的阻塞操作

fork子进程时,会产生阻塞主线程,因为会复制父进程的数据到子进程,但是fork不会把所有的内存数据都copy到子进程,只会copy一部分有用的数据到子进程中。

同时fork采用到操作系统的写时复制机制,每当有新的写命令,就会触发这个机制,此时就会把这新的命令写到旧AOF日志文件的缓冲区,等待数据重写完成后,重写的日志与缓冲区修改的数据进行合并,这样保证了AOF再父子进程之间的数据同步,再就是再重写时可以对外提供操作。

fork在复制内存页的时候会大量的消耗CPU资源,如果复制的内存页越大,fork阻塞的时间就会越久。拷贝内存页完成,子进程与父进程指向相同的内存地址。

父子进程分离:fork出的子进程与父进程指向的时同样的地址空间,然后子进程就可以完成AOF重写了,在这个过程中如果父进程有新的写命令,父进程会为这个key申请新的内存空间,慢慢的就会让父进程内存数据渐渐的进行分离。

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

搞数学的小混混

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

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

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

打赏作者

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

抵扣说明:

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

余额充值