深入浅出AOF功能和AOF重写两个知识点
本文默认你是使用过redis并了解redis的基础概念,学习redis入门并不难,给你介绍各种API使用也没啥意思。在这里 不会给你堆各种专业词汇,只有我个人理解的大白话
这里没别的 先来张总原理图,花10秒时间记一下,跟游戏打副本一样,先看下地图 做到脑子里有个大概的脉络,这里也是平时工作中比较常用的一种工作思考方式,遇到难的问题如果没思路就先忙别的,我们的大脑会在后台保持这个问题并且会时不时的激活一下,同样的时间做了多件事。高考时老师说拿到试卷先看一遍最后的作文题目在开始答题,一样的思想
AOF功能工作原理和AOF重写原理总图:
10秒已过 ,开始正文
一。AOF
1.说白了就是个日志记录文件。redis会把所有写命令记录到一个设定好的日志文件中,做开发的都知道 存储日志 是需要有 特定的格式的,这样后面你才能快速的定位检索,AOF里存储的是Redis自己定义的RESP协议格式的字符串,对,你没 看错就是字符串,(resp协议的https://blog.csdn.net/wenmeishuai/article/details/106101762)
2.AOF里记录的是每一次写命令,比如说list数据类型,其中有100条数据,在AOF中可能就有100条RESP协议的记录, 参考RESP的文章就知道,这其中有大量的重复命令
3.开启AOF持久化功能只需改两个配置参数
appendonly yes 开启aof
appendfilename mads.aof 日志文件名字,随便起
4.人是个喜欢刨根问底的生物,用是会用了。它是怎么实现的?
1)上面图中 红色框内是AOF的流程。 主进程接收客户端请求写命令,写入到aof_buf(aof缓冲区)然后主进程就返回了 (redis的优化点)
2)有专门的子进程去调用fsync()函数把数据从aof_buf写入到aof文件(谁在说redis是单线程就对他说:哼 初级程序员)
3)结合上面2)子进程该什么时候去触发调用fsync()这个同步动作呢,redis已经帮我们提前设置了三种策略:
ps:fsync()函数要求操作系统马上把aof_buf数据写到磁盘上.
配置文件中
appendfsync always
appendfsync everysec
appendfsync no
# no:不要立刻刷,只有在操作系统需要刷的时候再刷 ,比较快。如果redis重启了拿到的数据将不是很新的数据
# always:每次写操作都立刻写入到aof文件。慢,但是最安全。
# everysec:每秒写一次。折衷方案。 (默认,如果拿不准就用 "everysec"试水 )
4)AOF追加阻塞
结合上面继续深入,如果上面我设置的是每1秒同步一次数据,在线上大批量写请求下aof_buf有大量数据需要同步,此时 就会对磁盘进行高频写入,磁盘IO就变成了瓶颈,就会出现上次的同步动作还没完成
主进程又接收到大批写命令写到了缓冲区,此时redis为了保证aof文件安全性,会阻塞主线程,直到上次fsync同步完成。
主进程吧数据写入到aof_buf后会对比上次fsync操作时间,此时有两种情况:
1.如果距离上次fsync操作时间大于2S则阻塞主进程直到fsync结束
2.如果距上次操作时间小于2S则主进程直接返回
这里虽然我们配置的是每秒同步一次,但是实际上不是丢失1S的数据,实际上可能丢失2S数据,这里请细品
5)aof_buf同步到文件的流程 执行之前,看总量,依次执行,执行完成了再回收(清空)缓冲区
6)aof_buf里存储的格式是 RESP协议格式,(还没有看源码确认)
二。AOF重写
1.通过上面已经知道了AOF记录的是字符串。真正线上环境写操作是很多的,AOF的文件大小增加也是很快的,如果一个 AOF文件有10G了再去追加的时候那是非常慢的了。
2. redis就提供了一种压缩的方式,比如还是上面list数据类型100条数据,经过压缩以后就变成了一条,这就是AOF重写。
3.AOF重写会触发Redis的缓存淘汰策略,可以参考aof_rewrite函数源码,参考这篇文章 https://blog.csdn.net/qq_41453285/article/details/103301715
具体流程:
1.Redis开启了持久化功能,并且达到了重写的条件。三个参数,
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# 自动重写AOF文件
# 如果AOF日志文件大到指定百分比,Redis能够通过 BGREWRITEAOF 自动重写AOF日志文件。
# 工作原理:Redis记住上次重写时AOF日志的大小(或者重启后没有写操作的话,那就直接用此时的AOF文件),
# 基准尺寸和当前尺寸做比较。如果当前尺寸超过指定比例,就会触发重写操作。
# 你还需要指定被重写日志的最小尺寸,这样避免了达到约定百分比但尺寸仍然很小的情况还要重写。
# 指定百分比为0会禁用AOF自动重写特性。
2.调用fork系统级别函数,复制出完全一致的一个子进程,和主进程共用同一块内存空间(类似浅复制,redis为了节省内存开 销的优化点)
3.子进程调用aof_rewrite函数(redis客户端执行bgrewriteaof命令最终也是调用此函数)可以创建新的AOF文件去执行重写操作 根据已有数据进行命令的压缩和过期时间的检测并将压缩后的命令写入到新的AOF文件,直到写完
4.在AOF重写过程中,主进程是可以继续对外服务的,当接收到写命令,写入到aof_buf后,然后判断此时是否正在执行重写 操作,如果是再将写命令写入 到AOF重写缓冲区,主进程返回
5.当子进程完成对AOF文件重写之后,它会向父进程发送一个完成信号,父进程接到该完成信号之后,会调用一个信号处理函 数,该函数完成以下工作:
1).将AOF重写缓存中的内容全部写入到新的AOF文件中;这个时候新的AOF文件所保存的数据库状态和服务器当前的数 据库状态一致;
2).对新的AOF文件进行改名,原子的覆盖原有的AOF文件;完成新旧两个AOF文件的替换。到这里才是一次完整的AOF 重写流程
3).当这个信号处理函数执行完毕之后,主进程就可以继续像往常一样接收命令请求了。在整个AOF后台重写过程中,只有 最后的“主进程写入命令到AOF缓存”和“对新的AOF文件进行改名,覆盖原有的 AOF文件。”这两个步骤(信号处理函数 执行期间)会造成主进程阻塞,在其他时候,AOF后台重写都不会对主进程造成阻塞,这将AOF重写对性能造成的影 响降到最低。
6.如果AOF重写失败 redis会删除中间临时产物,保证流程的健壮性
AOF后台重写为什么这么干
1.aof_rewrite这个函数会进行大量的写入 操作,所以调用这个函数的线程将被长时间的阻塞,因为Redis服务器使用单线程来处理命令请求;所以如果直接是服务器进 程调用AOF_REWRITE函数的话,那么重写AOF期间,服务器将无法处理客户端发送来的命令请求;
2.Redis不希望AOF重写会造成服务器无法处理请求,所以Redis决定将AOF重写程序放到子进程(后台)里执行。这样处理的最 大好处是:
1)子进程进行AOF重写期间,主进程可以继续处理命令请求;
2)子进程带有主进程的数据副本,使用子进程而不是线程,可以避免在锁的情况下,保证数据的安全性。
使用子进程进行AOF重写的问题
3.子进程在进行AOF重写期间,服务器进程还要继续处理命令请求,而新的命令可能对现有的数据进行修改,这会让当前数 据库的数据和重写后的AOF文件中的数据不一致。
如何修正
1.为了解决这种数据不一致的问题,Redis增加了一个AOF重写缓存,这个缓存在fork出子进程之后开始启用,Redis服务器主 进程在执行完写命令之后,会同时将这个写命令追加到AOF缓冲区和AOF重写缓冲区
2.即子进程在执行AOF重写时,主进程需要执行以下三个工作:
执行client发来的命令请求;
将写命令追加到现有的AOF文件中;
将写命令追加到AOF重写缓存中。
最后记录下我的思考
1.写文件是很耗时的,数据多时还会出现阻塞。熟悉操作系统的同学会有个印象,数据从缓冲区到磁盘的过程也要经过内 核态到用户态的转换出现上下文切换,这个过程会很长,(Netty零拷贝可以看看)
2.Redis设计初衷就是快,10W+的QPS 也就是1ms就要处理100个命令,阻塞对于redis无疑是不可接受的,如果你是 redis作者会怎么解决呢,很简单的能想到就是同步转异步嘛,让会产生阻塞或者耗时的操作由子线程去干就好了, 主进程就专注处理客户端请求就好了(重点记忆,主进程只跟客户端打交道,其他全交给子进程),专业的人干专业 的事,人类发展史中 分工产生效能 也是这个思想。
3.追加阻塞这里,为什么不采用队列或多线程的方式来让主进程迅速返回?考虑是 增加额外的处理肯定要增加技术复杂 度和资源的消耗,。。。
4.其实最后发现并没有什么高大上的解决方案对不对。基础真的很重要呀。并且优化是从各个细节来的,也是个持续的 过程,成熟的架构都是慢慢演进的,
最后抛几个问题看看掌握没有
1.redis是单线程么?
2.为什么要子进程呢?因为万一重写失败。不会造成redis的死掉
3.为什么使用子进程而不是线程?可以避免在锁的情况下,保证数据的安全性。
4.为什么主子公用内存空间? 省空间,redis是内存数据库,留着内存干正事不香么
redis配置参数很全的一篇
https://www.cnblogs.com/xuliangxing/p/7151685.html
深入浅出AOF功能和AOF重写两个知识点相关推荐
- Redis 中的 持久化 AOF持久化 打开AOF持久化功能 设置AOF文件的冲洗频率 AOF重写 AOF持久化的优缺点
这里写目录标题 15.2 AOF持久化 15.2.1 打开AOF持久化功能 15.2.2 设置AOF文件的冲洗频率 15.2.3 AOF重写 1.BGREWRITEAOF命令 其他信息 2.AOF重写 ...
- Redis集群CentOS系统配置企业级数据备份方案以及数据恢复的操作(在开启AOF功能下恢复冷备RDB文件数据,保持AOF和RDB双开情况下恢复数据及错误的数据恢复步骤详解)
1. 设置每小时保存一份 /var/redis/6379/dump.rdb 文件至指定目录(我这边存放在 /usr/local/redis_backup 目录下),并删除48小时前的文件. 为 ...
- 25.请编写一个函数fun,它的功能是:比较两个字符串的长度,(不得调用C语言提供的求字符串长度的函数),函数返回较长的字符串。若两个字符串长度相同,则返回第一个字 符串。
25.请编写一个函数fun,它的功能是:比较两个字符串的长度,(不得调用C语言提供的求字符串长度的函数),函数返回较长的字符串.若两个字符串长度相同,则返回第一个字 符串. 例如,输入:beijing ...
- 傲游浏览器分屏功能:跑男 购物两不误
本文讲的是 : 傲游浏览器分屏功能:跑男 购物两不误 , 想购物,还想看一箩筐的综艺节目.电影大片儿?调成两个浏览器窗口又嫌太麻烦?如果没有用过傲游浏览器的分屏功能,就不要和我说你会用浏览器啦!一 ...
- win7计算机双击空白,Win7系统电脑Windows功能无法显示怎么办|Windows功能显示空白的两种解决方法...
Win7系统电脑的Windows功能设置可以从控制面板打开,通常情况下,等待几秒变回显示内容.可是有小伙伴却发现Windows功能窗口打开后什么都没有显示,一片空白.这有可能是系统的相关服务无意中被关 ...
- Eureka和zookeeper都可以提供服务注册与发现的功能,请说说两个的区别
古人语:独学而无友,则孤陋而寡闻.今效仿先贤,欲结交IT界之通道,帮助梳理开发通用的方法,供后来IT男学习,以成事温家之用.QQ:852383695 Eureka和zookeeper都可以提供服务注册 ...
- java 分布式计算框架_学Java分布式和高级架构,必懂的两大知识点!
原标题:学Java分布式和高级架构,必懂的两大知识点! 第一部分:分布式 三步变成:分布式 1.将你的整个软件视为一个系统(不管它有多复杂) 2.将整个系统分割为一系列的 Process(进程), 每 ...
- 一个一元二次方程求解编程引申的两个知识点(abs和fabs的区别以及浮点数比较相等)...
</pre>源程序如下:<p></p><p></p><pre name="code" class="cp ...
- python银行家算法例题详解_攒人品之作-能考408大题的知识点整理(有两个知识点的补充)...
本帖最后由 wudi971 于 2014-1-5 17:47 编辑 ::98::明年出题那么综合,我对不起大家...::116:: 经过陈123同学的提醒,补充两个知识点: 组成原理的微指令的设计以及 ...
最新文章
- Windows搭建golang开发平台
- Jenkins --SVN
- 2021天猫双11:阿里巴巴业务已全部跑在阿里云上
- 一文了解 Spring Boot 服务监控,健康检查,线程信息,JVM堆信息,指标收集,运行情况监控!...
- Redis常见面试题与答案
- jmeter中控制器3个请求其中一个访问不到_性能测试干货丨盘点JMeter常见的逻辑控制器...
- Python练习:星号三角形 I
- 华为云 - 公有云产品 - OBS计费说明
- 【报告分享】基础设施的新兴趋势-毕马威.pdf(附pdf下载链接)
- Python利用Beautiful Soup抓取新闻标题
- php fpm 报错,php-fpm报错
- 金色传说:SAP-BC-导出数据时不能选择导出文件的格式问题
- Codeforces Round #714 (Div. 2) B. AND Sequences (思维)
- SAP 移动平均价和标准价详细解析
- 和平精英分数计算机制,和平精英段位对应的积分完整一览 和平精英多少分上王牌...
- 达内2016前端开发知识点总结--HTML5--8天
- background-clip属性详解
- NOJ 1116 哈罗哈的大披萨 【淡蓝】 [状压dp+各种优化]
- Haproxy基础知识 -运维小结
- 第一章:电子商务的概述
热门文章
- Python中列表截取(Slice,即冒号 : )的用法详解
- [FireDAC][Phys][SQLite]-326. Cannot perform the action, because the previous action is in progress.
- SQL server触发器 inserted表和deleted表用法
- python QQ群发剪贴板消息
- 这21本关于商业的书你读过几本?
- IGeometry转WKT
- android ophone开发...,(OPhone、android讲义.doc
- 2021年50道Java线程面试题
- 河北省计算机专业对口大学分数线,官方发布!河北省2020年普通高校录取分数线高考录取分数线...
- 算法--冒泡排序原理