热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Redis持久化的研究—AOF

Redis持久化的研究Redis的持久化的方式----AOF在redis中存在一个日志文件(aof日志),此日志文件中保存着在redis中执行的有效的命令;当需要进行数据恢复时就会

Redis持久化的研究

Redis的持久化的方式----AOF

在redis中存在一个日志文件(aof日志),此日志文件中保存着在redis中执行的有效的命令;

当需要进行数据恢复时就会加载该文件,在redis重新执行一边来达到恢复数据的目的;


此处需要注意

AOF日志文件采用的是写后日志

写前日志:在实际写数据之前,先将修改数据的记录写道日志文件中;

写后日志:先执行命令,把数据写入到内存,然后再去记录日志



AOF采用写后日志的原因


在AOF文件中记录的并不是Redis识别的指令,而是经过了一次转换

//执行的命令
set test01 18
//在AOF文件中存储的"命令"
*3 //*3”表 ⽰当前命令有三个部分
$3 //此命令3个字节
set
$6 //此键6个字节
test01
$2 //此值2个字节
18 //*3”表 ⽰当前命令有三个部分,每部分都是由“$+数字”开头,后⾯紧跟着具体的命令、键或值。这⾥,“数 字”表⽰这部分中的命令、键或值⼀共有多少字节。

​ 为了避免额外的检查开销,Redis在向AOF⾥⾯记录⽇志的时候,并不会先去对这些命令进⾏语法检查。所以,如果先记⽇志再执⾏命令的话,⽇志中就有可能记录了错误的命令,Redis在使⽤⽇志恢复数据 时,就可能会出错。

​ 写后⽇志这种⽅式,就是先让系统执⾏命令,只有命令能执⾏成功,才会被记录到⽇志中,否则,系统就会直接向客⼾端报错。所以:

Redis使⽤写后⽇志这⼀⽅式的⼀⼤好处是,可以避免出现记录错误命令的情况。

第二个好处就是它是在命令执⾏后才记录⽇志,所以不会阻塞当前的写操作。



AOF的潜在风险


风险一:

如果刚执⾏完⼀个命令,还没有来得及记⽇志就宕机了,那么这个命令和相应的数据就有丢失的⻛ 险。如果此时Redis是⽤作缓存,还可以从后端数据库重新读⼊数据进⾏恢复,但是,如果Redis是直接⽤作数据库的话,此时,因为命令没有记⼊⽇志,所以就⽆法⽤⽇志进⾏恢复了。

风险二:


[重要知识点]:redis中的aof文件写入的操作是主线程执行的

如果在把⽇志⽂件写⼊磁盘时,磁盘写压⼒⼤,就会导致写盘很慢,进⽽导致后续的操 作也⽆法执⾏了。

(当大量的请求进来的,如果此时主线程在执行向AOF文件写数据的任务,那么后面进来的请求就会被阻塞,导致出现卡顿------查询操作也会进入等待)



三种回写的策略


经过分析不难发现:AOF持久化的两种风险都是因为落盘导致的

(落盘--->主线程向AOF文件中写数据 aof文件存在于磁盘 在进行磁盘读写都相较慢)

所有AOF配置项也提供了三个可选值------->三种回写的策略


Always:

​ 同步写回:每个写命令执⾏完,⽴⻢同步地将⽇志写回磁盘。

优点:可以做到基本不丢数据

缺点:每⼀个写命令后都有⼀个慢速的落盘操作,不可避免地会影响主线程性能;


Every sec:

​ 每秒写回:每个写命令执⾏完,只是先把⽇志写到AOF⽂件的内存缓冲区,每隔⼀秒把缓冲区中的内容写⼊磁盘。

优点:避免了“同步写回”的性能开销,减少了对系统性能的影响

缺点:如果发⽣宕机,上⼀秒内未落盘的命令操作仍然会丢失。


No:

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

“操作系统控制的写回”在写完缓冲区后,就可以继续执⾏后续的命令,但是落盘的时机已经不在 Redis⼿中了,只要AOF记录没有写回磁盘,⼀旦宕机对应的数据就丢失了;

优点:效率最高,主线程完全不受影响

缺点:随时都可能丢失数据


选择的方式:

可以根据系统对⾼性能和⾼可靠性的要求,来选择使⽤哪种写回策略了。



  • 想要获得⾼性能,就选择No策略;

  • 如果想要得到⾼可靠性保证,就选择Always策略;

  • 如果允许数据有⼀点丢 失,⼜希望性能别受太⼤影响的话,那么就选择Everysec策略。




AOF文件过大问题


AOF是以⽂件的形式在记录接 收到的所有写命令。随着接收的写命令越来越多,AOF⽂件会越来越⼤。这也就意味着,我们⼀定要⼩⼼ AOF⽂件过⼤带来的性能问题。

⼀是,⽂件系统本⾝对⽂件⼤⼩有限制,⽆法保存过⼤的⽂件;

⼆是,如果⽂件太⼤,之后再往⾥⾯追加命令记录的话,效率也会变低;

三是,如果发⽣宕机,AOF中 记录的命令要⼀个个被重新执⾏,⽤于故障恢复,如果⽇志⽂件太⼤,整个恢复过程就会⾮常缓慢,这就会 影响到Redis的正常使⽤。



重写机制--针对AOF文件过大的方案


Redis根据数据库的现状创建⼀个新的AOF⽂件,也就是说,读取数据库中的所有键值对,然后对每⼀个键值对⽤⼀条命令记录它的写⼊

重写机制的几个重要点:

主线程会forkc出后台的bgrewriteao子进程,不是由主线程完成;

Redis会读取数据库中的所有键值对,然后对每⼀个键值对⽤⼀条命令记录它的写⼊。--(旧⽇志⽂件中的多条命令,在重写后的新⽇志中变成了⼀条命令。)

重写的过程总结:

一个拷贝:


“⼀个拷⻉”**就是指,每次执⾏重写时,主线程fork出后台的bgrewriteaof⼦进程。此时,fork会把主线程 的内存拷⻉⼀份给bgrewriteaof⼦进程,这⾥⾯就包含了数据库的最新数据。然后,bgrewriteaof⼦进程就 可以在不影响主线程的情况下,逐⼀把拷⻉的数据写成操作,记⼊重写⽇志。


两处日志:


​ 因为主线程未阻塞,仍然可以处理新来的操作。此时,如果有写操作,第⼀处⽇志就是指正在使⽤的AOF⽇志,Redis会把这个操作写到它的缓冲区。这样⼀来,即使宕机了,这个AOF⽇志的操作仍然是⻬全的,可 以⽤于恢复。【aof日志缓冲区刷盘很快,丢数据最低可以控制到1s,业务能容忍】

​ ⽽第⼆处⽇志,就是指新的AOF重写⽇志。这个操作也会被写到重写⽇志的缓冲区。这样,重写⽇志也不会丢失最新的操作。等到拷⻉数据的所有操作记录重写完成后,重写⽇志记录的这些最新操作也会写⼊新的 AOF⽂件,以保证数据库最新状态的记录。此时,我们就可以⽤新的AOF⽂件替代旧⽂件了。

[等子线程完成了新的AOF日志的重写就会向主线程发信号,当主线程接收到了之后,

1.就会将缓存去的数据向新的日志中保存,

2.将新的日志文件替换掉原有的日志文件]

注意


若原有的内存数据是A, 那重写AOF时,fork后父子进程都会指向A地址,当新的写入进来时,父进程会拷贝数据(新的key直接申请内存就写了),而子进程访问A逐渐写入到重写AOF中,写完通知父进程,父进程会把写到缓冲的新key,再追加到重写AOF中。

这里只有AOF缓冲区,AOF重写缓冲区(这是两个不同缓冲区),写入新数据会写入两个缓冲区。之所以写入AOF缓冲区(后续写入AOF文件)是为了防止宕机而冗余的数据,而AOF重写缓冲区是在重写日志文件生成后,再追加到重写日志文件中,最后再将重写日志文件命名为AOF日志文件。



这两个配置项的意思是,在aof文件体量超过64mb,且比上次重写后的体量增加了50%时自动触发重写。



深入理解(常回顾理解)

AOF 日志重写的时候,是由 bgrewriteaof 子进程来完成的,不用主线程参与,我们今天说的非阻塞也是指子进程的执行不阻塞主线程。但是这个重写过程会有没有其他潜在的阻塞风险


a. fork子进程,fork这个瞬间一定是会阻塞主线程的(注意,fork时并不会一次性拷贝所有内存数据给子进程),fork采用操作系统提供的写实复制(Copy On Write)机制,就是为了避免一次性拷贝大量内存数据给子进程造成的长时间阻塞问题,但fork子进程需要拷贝进程必要的数据结构,其中有一项就是拷贝内存页表(虚拟内存和物理内存的映射索引表),这个拷贝过程会消耗大量CPU资源,拷贝完成之前整个进程是会阻塞的,阻塞时间取决于整个实例的内存大小,实例越大,内存页表越大,fork阻塞时间越久。拷贝内存页表完成后,子进程与父进程指向相同的内存地址空间,也就是说此时虽然产生了子进程,但是并没有申请与父进程相同的内存大小。那什么时候父子进程才会真正内存分离呢?“写实复制”顾名思义,就是在写发生时,才真正拷贝内存真正的数据。

b、 fork出的子进程指向与父进程相同的内存地址空间,此时子进程就可以执行AOF重写,把内存中的所有数据写入到AOF文件中。但是此时父进程依旧是会有流量写入的,如果父进程操作的是一个已经存在的key,那么这个时候父进程就会真正拷贝这个key对应的内存数据,申请新的内存空间,这样逐渐地,父子进程内存数据开始分离。

AOF重写不复用AOF本身的日志,一个原因是父子进程写同一个文件必然会产生竞争问题,控制竞争就意味着会影响父进程的性能。二是如果AOF重写过程中失败了,那么原本的AOF文件相当于被污染了,无法做恢复使用。所以Redis AOF重写一个新文件,重写失败的话,直接删除这个文件就好了,不会对原先的AOF文件产生影响。等重写完成之后,直接替换旧文件即可。





思考


1、如果写入内存成功了,在写入aof日志的时候失败了,宕机数据会不会丢失,有什么处理机制吗

我的理解:

当Redis只开启了aof的持久化时:没有将数据写入到日志文件就宕机,那么数据是肯定会丢失的;

所以采用RDB持久化配合AOF的持久化一起使用,数据的安全性将更加高

redis-check-aof --fix xx.aof



2、什么时候会触发AOF 重写呢?

①: 手动发送“bgrewriteaof”指令,通过子进程生成更小体积的aof,然后替换掉旧的、大体量的aof文件

②:配置自动触发

​ 1)auto-aof-rewrite-percentage 50

​ 2)auto-aof-rewrite-min-size 64mb



关于AOF的总结


AOF两大好处:

1、避免出现记录错误命令的情况;

2、它是在命令执行后才记录日志,所以不会阻塞当前的写操作。;

AOF两大风险:

1、还没有来得及记日志就宕机,命令和相应数据就丢失了;

2、日志写入磁盘,影响后续AOF落盘操作;

AOF的工作原理:

1、Redis 执行 fork() ,现在同时拥有父进程和子进程。

2、子进程开始将新 AOF 文件的内容写入到临时文件。

3、对于所有新执行的写入命令,父进程一边将它们累积到一个内存缓存中,一边将这些改动追加到现有 AOF 文件的末尾,这样样即使在重写的中途发生停机,现有的 AOF 文件也还是安全的。

4、当子进程完成重写工作时,它给父进程发送一个信号,父进程在接收到信号之后,将AOF重写缓存中的内容全部写入到新的AOF文件中。

5、对新的AOF文件进行改名,原子的覆盖原有的AOF文件;完成新旧两个AOF文件的替换。



拓展了解


写时复制机制(Copy-on-write,简称COW)是一种计算机程序设计领域的优化策略。其核心思想是,如果有多个调用者(callers)同时要求相同资源(如内存或磁盘上的数据存储),他们会共同获取相同的指针指向相同的资源,直到某个调用者试图修改资源的内容时,系统才会真正复制一份专用副本(private copy)给该调用者,而其他调用者所见到的最初的资源仍然保持不变。这过程对其他的调用者都是透明的(transparently)。此作法主要的优点是如果调用者没有修改该资源,就不会有副本(private copy)被创建,因此多个调用者只是读取操作时可以共享同一份资源。




推荐阅读
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 本文介绍了Redis中RDB文件和AOF文件的保存和还原机制。RDB文件用于保存和还原Redis服务器所有数据库中的键值对数据,SAVE命令和BGSAVE命令分别用于阻塞服务器和由子进程执行保存操作。同时执行SAVE命令和BGSAVE命令,以及同时执行两个BGSAVE命令都会产生竞争条件。服务器会保存所有用save选项设置的保存条件,当满足任意一个保存条件时,服务器会自动执行BGSAVE命令。此外,还介绍了RDB文件和AOF文件在操作方面的冲突以及同时执行大量磁盘写入操作的不良影响。 ... [详细]
  • 本文介绍了H5游戏性能优化和调试技巧,包括从问题表象出发进行优化、排除外部问题导致的卡顿、帧率设定、减少drawcall的方法、UI优化和图集渲染等八个理念。对于游戏程序员来说,解决游戏性能问题是一个关键的任务,本文提供了一些有用的参考价值。摘要长度为183字。 ... [详细]
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • RouterOS 5.16软路由安装图解教程
    本文介绍了如何安装RouterOS 5.16软路由系统,包括系统要求、安装步骤和登录方式。同时提供了详细的图解教程,方便读者进行操作。 ... [详细]
  • 从Oracle安全移植到国产达梦数据库的DBA实践与攻略
    随着我国对信息安全和自主可控技术的重视,国产数据库在党政机关、军队和大型央企等行业中得到了快速应用。本文介绍了如何降低从Oracle到国产达梦数据库的技术门槛,保障用户现有业务系统投资。具体包括分析待移植系统、确定移植对象、数据迁移、PL/SQL移植、校验移植结果以及应用系统的测试和优化等步骤。同时提供了移植攻略,包括待移植系统分析和准备移植环境的方法。通过本文的实践与攻略,DBA可以更好地完成Oracle安全移植到国产达梦数据库的工作。 ... [详细]
  • 本文介绍了一种轻巧方便的工具——集算器,通过使用集算器可以将文本日志变成结构化数据,然后可以使用SQL式查询。集算器利用集算语言的优点,将日志内容结构化为数据表结构,SPL支持直接对结构化的文件进行SQL查询,不再需要安装配置第三方数据库软件。本文还详细介绍了具体的实施过程。 ... [详细]
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了软件测试知识点之数据库压力测试方法小结相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 一次上线事故,30岁+的程序员踩坑经验之谈
    本文主要介绍了一位30岁+的程序员在一次上线事故中踩坑的经验之谈。文章提到了在双十一活动期间,作为一个在线医疗项目,他们进行了优惠折扣活动的升级改造。然而,在上线前的最后一天,由于大量数据请求,导致部分接口出现问题。作者通过部署两台opentsdb来解决问题,但读数据的opentsdb仍然经常假死。作者只能查询最近24小时的数据。这次事故给他带来了很多教训和经验。 ... [详细]
  • Centos下安装memcached+memcached教程
    本文介绍了在Centos下安装memcached和使用memcached的教程,详细解释了memcached的工作原理,包括缓存数据和对象、减少数据库读取次数、提高网站速度等。同时,还对memcached的快速和高效率进行了解释,与传统的文件型数据库相比,memcached作为一个内存型数据库,具有更高的读取速度。 ... [详细]
  • 本文介绍了关系型数据库和NoSQL数据库的概念和特点,列举了主流的关系型数据库和NoSQL数据库,同时描述了它们在新闻、电商抢购信息和微博热点信息等场景中的应用。此外,还提供了MySQL配置文件的相关内容。 ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • Tomcat/Jetty为何选择扩展线程池而不是使用JDK原生线程池?
    本文探讨了Tomcat和Jetty选择扩展线程池而不是使用JDK原生线程池的原因。通过比较IO密集型任务和CPU密集型任务的特点,解释了为何Tomcat和Jetty需要扩展线程池来提高并发度和任务处理速度。同时,介绍了JDK原生线程池的工作流程。 ... [详细]
author-avatar
风过无痕啦啦
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有