Redis的持久化主要有两大机制,即AOF日志和RDB快照
AOF日志
1.2 AOF日志是如何实现的?
说到⽇志,我们⽐较熟悉的是数据库的写前⽇志(Write Ahead Log, WAL)——例如mysql的redolog,也就是说,在实际写数据前,先把修改的数据记到⽇志⽂件中,以便故障时进⾏恢复。不过,AOF⽇志正好相反,它是写后⽇志,“写后”的意思是Redis是先执⾏命令,把数据写⼊内存,然后才记录⽇志,如下图所示:
 
那AOF为什么要先执⾏命令再记⽇志呢?
1、AOF⾥记录的是Redis收到的每⼀条命令,这些命令是以⽂本形式保存的。
2、为了避免额外的检查开销,Redis在向AOF⾥⾯记录⽇志的时候,并不会先去对这些命令进⾏语法检查。所以,如果先记⽇志再执⾏命令的话,⽇志中就有可能记录了错误的命令,Redis在使⽤⽇志恢复数据时,就可能会出错。
3、它是在命令执⾏后才记录⽇志,所以不会阻塞当前的写操作。
 
AOF两个潜在的⻛险
1、如果刚执⾏完⼀个命令,还没有来得及记⽇志就宕机了,那么这个命令和相应的数据就有丢失的⻛险。
2、AOF虽然避免了对当前命令的阻塞,但可能会给下⼀个操作带来阻塞⻛险。这是因为,AOF⽇志也是在主线程中执⾏的,如果在把⽇志⽂件写⼊磁盘时,磁盘写压⼒⼤,就会导致写盘很慢,进⽽导致后续的操作也⽆法执⾏了。
基于以上两点,如果我们能够控制⼀个写命令执⾏完后AOF⽇志写回磁盘的时机,这两个⻛险就解除了。
  • Always,同步写回:每个写命令执⾏完,⽴⻢同步地将⽇志写回磁盘;
  • Everysec,每秒写回:每个写命令执⾏完,只是先把⽇志写到AOF⽂件的内存缓冲区,每隔⼀秒把缓冲区中的内容写⼊磁盘;
  • No,操作系统控制的写回:每个写命令执⾏完,只是先把⽇志写到AOF⽂件的内存缓冲区,由操作系统决定何时将缓冲区内容写回磁盘。
 
AOF文档太大了怎么办?
随着输入的命令越来越多,这些命令都会被记录到AOF文件中,导致AOF文件过大。
 
AOF文件过大的问题:
系统发送宕机重启,从AOF文件恢复数据的速度很慢,影响业务。
占用系统磁盘
 
redis有AOF重写机制,当⼀个键值对被多条写命令反复修改时,AOF⽂件会记录相应的多条命令。但是,在重写的时候,是根据这个键值对当前的最新状态,为它⽣成对应的写⼊命令。
和AOF⽇志由主线程写回不同,重写过程是由后台线程bgrewriteaof来完成的,这也是为了避免阻塞主线程,导致数据库性能下降。
我把重写的过程总结为“⼀个拷⻉,两处⽇志”。
  • “⼀个拷⻉”就是指,每次执⾏重写时,主线程fork出后台的bgrewriteaof⼦进程。此时,fork会把主线程的内存拷⻉⼀份给bgrewriteaof⼦进程,这⾥⾯就包含了数据库的最新数据。然后,bgrewriteaof⼦进程就可以在不影响主线程的情况下,逐⼀把拷⻉的数据写成操作,记⼊重写⽇志。
  • “两处⽇志”⼜是什么呢?因为主线程未阻塞,仍然可以处理新来的操作。此时,如果有写操作,第⼀处⽇志就是指正在使⽤的AOF⽇志,Redis会把这个操作写到它的缓冲区。这样⼀来,即使宕机了,这个AOF⽇志的操作仍然是⻬全的,可以⽤于恢复。⽽第⼆处⽇志,就是指新的AOF重写⽇志。这个操作也会被写到重写⽇志的缓冲区。这样,重写⽇志也不会丢失最新的操作。等到拷⻉数据的所有操作记录重写完成后,重写⽇志记录的这些最新操作也会写⼊新的AOF⽂件,以保证数据库最新状态的记录。此时,我们就可以⽤新的AOF⽂件替代旧⽂件了。
 

 
Redis采⽤fork⼦进程重写AOF⽂件时,潜在的阻塞⻛险?
1:、fork⼦进程,fork这个瞬间⼀定是会阻塞主线程的(注意,fork时并不会⼀次性拷⻉所有内存数据给⼦进程),fork采⽤操作系统提供的写实复制(Copy On Write)机制,就是为了避免⼀次性拷⻉⼤量内存数据给⼦进程造成的⻓时间阻塞问题,但fork⼦进程需要拷⻉进程必要的数据结构,其中有⼀项就是拷⻉内存⻚表(虚拟内存和物理内存的映射索引表),这个拷⻉过程会消耗⼤量CPU资源,拷⻉完成之前整个进程是会阻塞的,阻塞时间取决于整个实例的内存⼤⼩,实例越⼤,内存⻚表越⼤,fork阻塞时间越久。拷⻉内存⻚表完成后,⼦进程与⽗进程指向相同的内存地址空间,也就是说此时虽然产⽣了⼦进程,但是并没有申请与⽗进程相同的内存⼤⼩。那什么时候⽗⼦进程才会真正内存分离呢?“写实复制”顾名思义,就是在写发⽣时,才真正拷⻉内存真正的数据,这个过程中,⽗进程也可能会产⽣阻塞的⻛险,就是下⾯介绍的场景。
fork出的⼦进程指向与⽗进程相同的内存地址空间,此时⼦进程就可以执⾏AOF重写,把内存中的所有数据写⼊到AOF⽂件中。但是此时⽗进程依旧是会有流量写⼊的,如果⽗进程操作的是⼀个已经存在的key,那么这个时候⽗进程就会真正拷⻉这个key对应的内存数据,申请新的内存空间,这样逐渐地,⽗⼦进程内存数据开始分离,⽗⼦进程逐渐拥有各⾃独⽴的内存空间。因为内存分配是以⻚为单位进⾏分配的,默认4k,如果⽗进程此时操作的是⼀个bigkey,重新申请⼤块内存耗时会变⻓,可能会产阻塞⻛险。另外,如果操作系统开启了内存⼤⻚机制(Huge Page,⻚⾯⼤⼩2M),那么⽗进程申请内存时阻塞的概率将会⼤⼤提⾼,所以在Redis机器上需要关闭Huge Page机制。Redis每次fork⽣成RDB或AOF重写完成后,都可以在Redis log中看到⽗进程重新申请了多⼤的内存空间。
 
AOF重写为什么新创建一个AOF日志文件,为什么不复用老的AOF文件?
  • AOF重写不复⽤AOF本⾝的⽇志,⼀个原因是⽗⼦进程写同⼀个⽂件必然会产⽣竞争问题,控制竞争就意味着会影响⽗进程的性能。
  • 如果AOF重写过程中失败了,那么原本的AOF⽂件相当于被污染了,⽆法做恢复使⽤。所以Redis AOF重写⼀个新⽂件,重写失败的话,直接删除这个⽂件就好了,不会对原先的AOF⽂件产⽣影响。等重写完成之后,直接替换旧⽂件即可。
 
内存快照—RDB
AOF记录的是操作命令,⽽不是实际的数据,所以,⽤AOF⽅法进⾏故障恢复的时候,需要逐⼀把操作⽇志都执⾏⼀遍。如果操作⽇志⾮常多,Redis就会恢复得很缓慢,影响到正常使⽤。
基于以上原因,redis有另外一套机制保持内存数据——内存快照
对Redis来说,它实现类似照⽚记录效果的⽅式,就是把某⼀时刻的状态以⽂件的形式写到磁盘上,也就是快照。这样⼀来,即使宕机,快照⽂件也不会丢失,数据的可靠性也就得到了保证。这个快照⽂件就称为RDB⽂件。
 
会阻塞主线程吗?
Redis提供了两个命令来⽣成RDB⽂件,分别是save和bgsave。
  • save:在主线程中执⾏,会导致阻塞;
  • bgsave:创建⼀个⼦进程,专⻔⽤于写⼊RDB⽂件,避免了主线程的阻塞,这也是Redis RDB⽂件⽣成的默认配置。
快照时数据能修改吗?
  • 如果快照执⾏期间数据不能被修改,是会有潜在问题的。在快照的Ns时间⾥,如果数据都不能被修改,Redis就不能处理对这些数据的写操作,那⽆疑就会给业务服务造成巨⼤的影响。
  • 如果使用bgsave命令,此时,主线程的确没有阻塞,可以正常接收请求,但是,为了保证快照完整性,它只能处理读操作,因为不能修改正在执⾏快照的数据。为了快照⽽暂停写操作,肯定是不能接受的。所以这个时候,Redis就会借助操作系统提供的写时复制技术(Copy-On-Write, COW)【当父线程操作一个已经存在的key时,会复制内存数据,另外开辟一块内存空间,当完成命令操作时,地址指向这个新的内存空间】,在执⾏快照的同时,正常处理写操作。
 
 
 
Redis 4.0中提出了⼀个混合使⽤AOF⽇志和内存快照的⽅法。简单来说,内存快照以⼀定的频率执⾏,在两次快照之间,使⽤AOF⽇志记录这期间的所有命令操作。这样⼀来,快照不⽤很频繁地执⾏,这就避免了频繁fork对主线程的影响。⽽且,AOF⽇志也只⽤记录两次快照间的操作,也就是说,不需要记录所有操作了,因此,就不会出现⽂件过⼤的情况了,也可以避免重写开销。
 

宕机了,Redis如何避免数据丢失?的更多相关文章

  1. Redis宕机的问题

    在主从模式下宕机要分为区分来看: slave从redis宕机 ​ 在Redis中从库重新启动后会自动加入到主从架构中,自动完成同步数据: ​ 如果从数据库实现了持久化,只要重新假如到主从架构中会实现增 ...

  2. [转帖]Redis持久化--Redis宕机或者出现意外删库导致数据丢失--解决方案

    Redis持久化--Redis宕机或者出现意外删库导致数据丢失--解决方案 https://www.cnblogs.com/xlecho/p/11834011.html echo编辑整理,欢迎转载,转 ...

  3. 04 AOF日志:宕机了,Redis如何避免数据丢失

    接下来两篇将记录Redis持久化存储两大技术:AOF日志.RDB快照 本篇重点 "AOF日志实现""AOF日志三种写回策略""AOF重写--避免日志过 ...

  4. Redis的KEYS命令引起宕机事件

    摘要: 使用 Redis 的开发者必看,吸取教训啊! 原文:Redis 的 KEYS 命令引起 RDS 数据库雪崩,RDS 发生两次宕机,造成几百万的资金损失 作者:陈浩翔 Fundebug经授权转载 ...

  5. redis集群节点宕机

    redis集群是有很多个redis一起工作,那么就需要这个集群不是那么容易挂掉,所以呢,理论上就应该给集群中的每个节点至少一个备用的redis服务.这个备用的redis称为从节点(slave). 1. ...

  6. redis宕机如何解决?如果是项目上线的宕机呢?

    我们先来了解一下  bridge网络模式 他会创建一个docker0桥,看完这个我们就会知道redis哨兵机制的端口了. 之后继续研究redis宕机的解决办法! 宕机: 服务器停止服务 如果只有一台r ...

  7. 宕机了,Redis数据丢了怎么办?

    持续原创输出,点击上方蓝字关注我 目录 前言 什么是AOF? 三种写回策略 日志文件太大怎么办? AOF重写会阻塞主线程吗? AOF的缺点 总结 什么是RDB? 给哪些数据做快照? 快照时能够修改数据 ...

  8. Redis 日志篇:无畏宕机快速恢复的杀手锏

    特立独行是对的,融入圈子也是对的,重点是要想清楚自己向往怎样的生活,为此愿意付出怎样的代价. 我们通常将 Redis 作为缓存使用,提高读取响应性能,一旦 Redis 宕机,内存中的数据全部丢失,假如 ...

  9. 由Redis的hGetAll函数所引发的一次服务宕机事件

    昨晚通宵生产压测,终于算是将生产服务宕机的原因定位到了,心累.这篇博客,算作一个复盘和记录吧... 先来看看Redis的缓存淘汰算法思维导图: 说明:当实际占用的内存超过Redis配置的maxmemo ...

  10. linux 双Redis + keepalived 主从复制+宕机自主切换

    主要核心思想,如果master 和 salve 全部存活的情况,VIP就漂移到 master.读写都从master操作,如果master宕机,VIP就会漂移到salve,并将之前的salve切换为ma ...

随机推荐

  1. PSPNet 代码分析

    https://www.lmlphp.com/user/62501/article/item/1225624/ train.py 网络训练主函数,主要操作有: 传入训练参数:通常采用argparse库 ...

  2. kubectl工具安装指南

    kubectl是一个用于连接Service Mesh控制平面的工具,可以安装在办公电脑的Windows系统上,也可以安装在虚拟机的Linux系统上,只要网络能与控制平面的公网地址互通即可.下面分别介绍 ...

  3. Loadrunner录制时弹出Microsoft Visual C++ Runtime Library解决方案

    这段时间用loadrunner测试工具,录制脚本的时候老是出现这个弹窗,刚开始就以为是软件错误,就用的软件修复,也解决了,后来还是出现这样的错误,修复也没有用 原因:可能是代理服务器在调用VC库的时候 ...

  4. 记录一次 网关负载 流量不均匀 cpu使用率不均衡问题

    网关负载  流量不均匀  cpu使用率不均衡问题??? 1.压力机访问源  有多少ip 有10个? 还是20个? 就是样本源不多的话,负载上hash的话  就你可能不是真实的访问需求 ,你客户端就那么 ...

  5. 【alive-progress】Python控制台输出动态进度条

    简介 alive-progress是一种具有实时吞吐量和非常酷的动画新型的进度条python库. 使用 from alive_progress import alive_bar import time ...

  6. Jmeter八、关联

    关联的方式:1.正则2.Xpath 后置 处理器→正则表达式提取器 正则表达式:(.*) 模板$1$ 匹配数字:0代表随机,-1代表所有 缺省值为空即可

  7. 通过Windows定时任务执行Python脚本给钉钉群发送消息

    前提:已经存在有成功发送钉钉群机器人消息的python脚本,参考上一篇Python调用钉钉群机器人发送群消息 Windows定时任务设置 1.本机是Win7系统:控制面板->系统和安全-> ...

  8. .netCore Nuget包引用记录

    1.画图  System.Drawing.Common 2.

  9. 20181224蒋嘉豪-exp3-免杀原理与实现

    20181224蒋嘉豪-exp3-免杀原理与实现 目录 20181224蒋嘉豪-exp3-免杀原理与实现 课上知识点总结 1.恶意软件检测机制 2.免杀技术综述 Exp3.1 能够正确使用msf编码器 ...

  10. 后端返回字符流,前端处理进行excel文件导出操作

    针对于这种的文件导出,最关键的是响应类型的设置,也就是responseType的设置(responseType:"arraybuffer"或者responseType:" ...