redis:持久化原理

redis是运行在内存中的数据库,数据的存储位置在内存这使得它具有更快的数据读写速度,但这并不意味着关个机数据全没了,redis有他自己的持久化机制

AOF持久化

简单来说就是创建一个AOF日志,它的作用是记录执行过的各种写指令,下次恢复状态时再执行一遍。
向AOF日志中写的时候会造成一次文件IO,所以一般在指令执行结束后进行写操作,这样一来可以避免指令错误二来不会阻塞写指令的执行,这个过程需要满足原子性,所以还是会对下一跳指令产生阻塞,参考MySQL这里可以加一个缓存池(server.aof_buf)用来缓存指令。
现在问题姑且是解决了,但是什么时候将缓存池的内容写入文件呢?

AOF写回策略

redis提供了3种写回策略,可以在redis.conf配置文件中的appendfsync配置项进行选择。

写回策略写回时机优点缺点
Always同步写回可靠性高,最大程度保证数据不丢失性能开销大
Everysec每秒写回性能适中服务器宕机时丢失1s内的数据
No由操作系统控制写回性能好服务器宕机时丢失的数据量未知

实现起来其实通过控制fsync的调用时机控制的

  • Always 策略就是每次写入 AOF 文件数据后,就执行 fsync() 函数;
  • Everysec 策略就会创建一个异步任务来执行 fsync() 函数;
  • No 策略就是永不执行 fsync() 函数;

AOF重写机制

写回策略是确定了,但是还是存在问题,一般情况看下一个服务器一旦开始跑就一直要跑下去(除非特殊情况),那么AOF日志的大小岂不太大了,里面的指令再次重启的时候又要跑多久呢?为了解决这个问题,redis引入了重写机制

简单来说就是文件大小到达一个阈值后会按照当前存储的数据给出复现指令,十分合理,这种情况下可以有效过滤掉一些中间指令,甚至可以按照当前情况进行指令优化。
下面介绍AOF重写过程

  • fork重写子进程
  • 子进程创建一个新的AOF日志,进行数据的反向复现,此时主进程还可以处理业务,但是写入的时候会触发写时复制,这个过程中新的写操作会写入旧的AOF缓冲区和AOF重写缓冲区
  • 子进程处理完后向主进程发送一个信号告知处理完毕,主进程接收到信号后调用信号处理函数,将AOF缓冲区内的临时数据拷贝到新的AOF日志中,新的AOF日志改名覆盖掉旧的日志

细节详解:

  1. 为什么使用子进程而不使用子线程,假设使用子线程的话试想一种情景对方取反,你这里还没有解析到,AOF重写缓冲区记录到了,你记录的也是修改后的,最后和并的时候就会出错,不记录缓冲区的话解析完string类型数据你又加入新数据也会出问题,加锁可以解决问题,但是代价太大了,不如借助父子进程间的写时复制原则保证原子性
  2. 阻塞环节:
  • 创建子进程时复制页表的环节
  • 写时复制的环节
  • 调用信号处理函数环节

RDB快照

启动快照的情况下redis会按照约定的时间拍快照,这个过程依旧是通过子进程完成的,相较于AOF日志这里存储的是真实数据,以二进制的方式存储到文件中,这使得快照恢复起来更加高效,高效的同时是更高的代价,极端情况下拷贝数据的时候如果父进程的数据全修改了就需要2x大小的物理内存。
巨大的性能开销决定了RDB快照无法经常进行,所以使用它的时候服务器宕机可能会造成大量数据丢失。

AOF结合RDB

这个方法是在 Redis 4.0 提出的,该方法叫混合使用 AOF 日志和内存快照,也叫混合持久化,启用的话将下面这个配置设置为true就行了。

aof-use-rdb-preamble yes

过程也很简单,在AOF重写的过程中进行,重写时直接拷贝数据并储存到新的AOF日志中,然后拷贝完将AOF重写缓冲区的内容以AOF指令的形式存储到新的AOF日志中,现在AOF由RDB快照和AOF指令组成,这种方式启动起来更加高效同时服务器宕机时数据保存效果好,简直是妙蛙种子吃着妙脆角进了米奇妙妙屋妙到家了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值