大家都知道Redis经常被使用在缓存的场景中,那有没有想过这么一个问题,一旦服务器宕机,内存中的数据全部丢失,我们该如何进行恢复呢?如果直接从后端数据库恢复,不仅会给数据库带来巨大的压力,还会使上层应用响应变慢。所以redis的持久化机制是很重要的。接下来我们一起来探讨一下Redis的持久化机制。目前Redis持久化主要有两大机制,即AOF(Append Only File)日志和RDB快照。接下来我们就来分别学习一下。

 AOF日志

AOF日志,即写后日志,它的含义是Redis先执行命令,把数据写入内存,然后再写入日志。Redis为什么要先执行命令后写入日志呢?首先我们来看一下AOF日志里记录了什么内容。AOF记录的是Redis收到的每一条命令,这些日志以文本的形式保存。假如我们执行了set hello world命令,AOF的内容如下:

其中“*3”代表当前命令有3部分,每部分是由”$+数字”开头,后面紧跟着具体命令、键和值。这里的数字代表后面的命令、键和值一共有多少个字节。例如 “$3 set”表示这部分有3个字节,也就是“set”命令。

Redis为了避免额外的检查开销,再往AOF里写入日志的时候,并不会对这些命令进行语法检查。所以如果先写日志再执行命令,日志中就可能会记录一些错误的命令,Redis使用日志恢复的时候就会出错。而写后日志这种方式,就是先去执行命令,如果命令执行出错,则不写入日志,只有执行成功的命令才会写入日志中。所以Redis使用写后日志这一方式的一大好处是,可以避免出现记录错误命令的情况。AOF还有一大好处,它是在命令执行后才记录日志,所以不会阻塞当前的写操作。

不过,AOF也有潜在的两个风险,首先如果刚执行完一个命令,还没来的及写日志就宕机了,那么这个命令和相应的数据就有丢失的风险。其次,AOF虽然避免了对当前命令的阻塞,但可能会给下一个操作带来阻塞风险。这是因为,AOF日志也是在主线程中执行的,如何在把日志文件写入磁盘很慢时,就会阻塞后续操作。针对这个问题,AOF给我们提供了三种写回策略,也就是AOF的配置项appendfsync的三个可选值。

  1. Always,同步写回:每个写命令执行完,立马同步地将日志写回磁盘;
  2. Everysec,每秒写回:每个写命令执行完,只是先把日志写到AOF文件的内存缓冲区,每隔一秒把缓冲区中的内容写入磁盘;
  3. No,操作系统控制的写回:每个写命令执行完,只是先把日志写到AOF文件的内存缓冲区,由操作系统决定何时将缓冲区内容写回磁盘。

这三种写回策略都无法做到两全其美,都有自己的优缺点,我们只能根据我们的业务场景,是需要高性能还是高可靠性来选择不同的写回策略。

最后,AOF还有一个问题,就是AOF以文件的形式记录在磁盘里。随着Redis接受的写命令越来越多,那么AOF日志文件也会越来越大,所以需要采取一定的手段来控制AOF日志文件的大小。这个时候,AOF重写机制就派上用场了。AOF重写机制是指在重写时,Redis会根据数据库的现状创建一个新的AOF文件,也就是说,读取数据库中的所有键值对,然后对每一个键值对用一条命令记录它的写入。为什么重写机制可以把日志文件变小呢?实际上,重写机制具有“多变一”功能。所谓的“多变一”,也就是说,旧日志文件中的多条命令,在重写后的新日志中变成了一条命令。例如我们对某个key进行了6次写入操作,那么旧的日志文件中就会有6条记录,而重写后的日志文件中就只有一条命令,所以AOF重写会减小文件的大小。那么AOF重写会阻塞主线程吗?毕竟把整个Redis的数据库的最新数据的操作日志都写回磁盘,仍然是一个非常耗时的过程。和AOF日志由主线程写回不同,重写过程是由后台子进程bgrewriteaof来完成的,这也是为了避免阻塞主线程,导致Redis的性能下降。每次执行重写时,主线程 fork 出后台的 bgrewriteaof 子进程。此时,fork 会把主线程的内存拷贝(采用操作系统的写时复制技术,不会真正的拷贝,写时复制技术下面会分析)一份给 bgrewriteaof 子进程,这里面就包含了数据库的最新数据。然后,bgrewriteaof 子进程就可以在不影响主线程的情况下,逐一把拷贝的数据写成操作,记入重写日志。因为主线程未阻塞,仍然可以处理新来的操作。为了避免数据丢失,在AOF重写过程中,新进入的写命令会写入到两份日志中。第一处日志就正在使用的 AOF 日志,Redis 会把这个操作写到它的缓冲区。这样一来,即使宕机了,这个 AOF 日志的操作仍然是齐全的,可以用于恢复。第二处日志,就是指新的 AOF 重写日志。这个操作也会被写到重写日志的缓冲区。这样,重写日志也不会丢失最新的操作。等到拷贝数据的所有操作记录重写完成后,重写日志记录的这些最新操作也会写入新的 AOF 文件,以保证数据库最新状态的记录。此时,我们就可以用新的 AOF 文件替代旧文件了。

RDB快照文件 

      由于AOF记录的是操作命令,而不是实际的数据。所以,用AOF方法进行故障恢复的时候,需要逐一把操作日志都执行一遍。如果操作日志很多,那Redis恢复的就很慢,影响到正常使用。那有没有即保证可靠性,还能在宕机时实现快速的恢复办法呢?那就是内存快照。对于Redis来说,它把某一时刻的状态以文件的形式写到磁盘上。这样一来,即使宕机,快照文件也不会丢失,数据的可靠性得到了保证。这个快照文件就叫RDB(Redis DataBase)文件。和AOF相比,RDB记录的是某一时刻的数据,并不是操作,所以,在做数据恢复时,直接把RDB文件加载到内存里,很快的完成恢复。

Redis提供了两个命令来生成RDB文件,分别是save和bgsave。

  1. save:在主线程中执行,会导致阻塞。
  2. bgsave:创建一个子进程,专门用于写入RDB文件,避免主线程的阻塞。这也是redis生成RDB文件的默认配置。

所以,我们可以采用bgsave来执行全量快照,既保证了可靠性,又避免了Redis的性能影响。接下了,我们来思考这么一个问题,就是Redis在做全量快照时,Redis中的数据可以被修改吗?Redis还支持写操作吗?为了快照而暂停写操作,Redis肯定是不能接受的。所以Redis借助了操作系统提供的写时复制技术(Copy-On-Write,COW)。简单来说,bgsave子进程是由主线程fork生成的,可以共享主线程的所有内存数据。bgsave运行之后,开始读取主线程中的内存数据,并把他们写入RDB文件。此时,如果主线程对这些数据进行读操作,则主线程和bgsave子进程相互不影响。但是,如果主线程执行写操作或者修改操作,也就是修改内存中的一块数据,那么这块数据会复制一份,生成副本。然后主线程在副本上进行修改。同时,bgsave子进程继续把原来的数据写入RDB文件。这样既保证了快照的完整性,也避免了对正常业务的影响。

      接下来我们来看下一个问题,就是多久做一次快照,如果快照隔的时间太久,丢的数据就越多,间隔时间太短,丢失的数据越少,但是频繁的执行全量快照会给磁盘带来很大的压力。由于fork创建子进程bgsave这个过程是需要阻塞主线程的,主线程的内存越大,fork时间越长。所以频繁的fork出bgsave子进程,也就会频繁阻塞主线程。那有什么好的办法既能利用RDB的快速恢复,又能以较小的开销做到尽量少丢数据呢。Redis4.0提出了一个混合使用AOF日志和RDB的方法。简单来说,内存快照以一定的频率执行,两次快照之间使用AOF记录操作命令。

最后总结一下,关于AOF和RDB的选择问题,给大家提供3点建议。

  1. 数据不能丢失时,内存快照和 AOF 的混合使用是一个很好的选择。
  2. 如果允许分钟级别的数据丢失,可以只使用 RDB。
  3. 如果只用 AOF,优先使用 everysec 的配置选项,因为它在可靠性和性能之间取了一个平衡。

 更多硬核知识,请关注公众号”老韩随笔"。

Redis的持久化机制你学会了吗的更多相关文章

  1. Redis数据持久化机制AOF原理分析一---转

    http://blog.csdn.net/acceptedxukai/article/details/18136903 http://blog.csdn.net/acceptedxukai/artic ...

  2. 10分钟彻底理解Redis的持久化机制:RDB和AOF

    作者:张君鸿 juejin.im/post/5d09a9ff51882577eb133aa9 什么是Redis持久化? Redis作为一个键值对内存数据库(NoSQL),数据都存储在内存当中,在处理客 ...

  3. Redis进阶:Redis的持久化机制

    Redis进阶:Redis的持久化机制 Redis的持久化机制目前包括RBD和AOF两种方式. RDB持久化 RDB持久化方式是在指定的时间间隔对数据进行快照存储.过期的键值不会被存储到快照中.如果恢 ...

  4. Redis的持久化机制与内存管理机制

    1.概述 Redis的持久化机制有两种:RDB 和 AOF ,这两种机制有什么区别?正式环境应该采用哪种机制? 我们的服务器内存资源是有限的,如果内存被Redis的缓存占满了怎么办?这就要看Redis ...

  5. Redis的持久化机制:RDB和AOF

    什么是Redis持久化? Redis作为一个键值对内存数据库(NoSQL),数据都存储在内存当中,在处理客户端请求时,所有操作都在内存当中进行,如下所示: 这样做有什么问题呢? 其实,只要稍微有点计算 ...

  6. Redis学习-持久化机制

    Redis持久化的意义 在于故障恢复 比如你部署了一个redis,作为cache缓存,当然也可以保存一些较为重要的数据 如果没有持久化的话,redis遇到灾难性故障的时候(断电.宕机),就会丢失所有的 ...

  7. Redis的持久化机制

    持久化机制 RDB:快照模式AOF :日志模式 多数据库– 一个redis服务器内部默认有16个数据,编号О0-15– 默认操作是编号为0的数据库– 可以在命令行用select选择数据库127.0.0 ...

  8. Redis的持久化机制是什么?各自的优缺点?

    Redis 提供两种持久化机制 RDB 和 AOF 机制: 1.RDBRedis DataBase)持久化方式:是指用数据集快照的方式半持久化模式) 记录 redis 数据库的所有键值对,在某个时间点 ...

  9. 深入理解Redis的持久化机制和原理

    Redis是一种面向“key-value”类型数据的分布式NoSQL数据库系统,具有高性能.持久存储.适应高并发应用场景等优势.它虽然起步较晚,但发展却十分迅速. 近日,Redis的作者在博客中写到, ...

随机推荐

  1. MySQL 基础、安装、配置

    1. MySQL 基础 1.1 什么是数据库? 1.2 数据库的类型 1.3 关系型数据库的优点 1.4 MySQL 简介 1.5 MySQL 数据类型 1.6 Mysql 存储引擎 1.7 MySQ ...

  2. 深度学习Anchor Boxes原理与实战技术

    深度学习Anchor Boxes原理与实战技术 目标检测算法通常对输入图像中的大量区域进行采样,判断这些区域是否包含感兴趣的目标,并调整这些区域的边缘,以便更准确地预测目标的地面真实边界框.不同的模型 ...

  3. ng : 无法加载文件 C:\Users\szz\AppData\Roaming\npm\ng.ps1,因为在此系统上禁止运行脚本的解决方案

    当安装好Angular CLI后想要查看该版本时在终端键入: ng version 后出现下图的错误提示 解决方案: 在win10 系统中有一个搜索框 输入 Windos PowerShell (一定 ...

  4. 四、SSL虚拟证书

    沿用练习三,配置基于加密网站的虚拟主机,实现以下目标: 域名为www.c.com 该站点通过https访问 通过私钥.证书对该站点所有数据加密 4.2 方案 源码安装Nginx时必须使用--with- ...

  5. Telnet查看端口是否通

    1. 查看端口是否通畅   telnet IP 端口号 如:telnet 10.150.159.71 5516 2.查看本机是否开启某个端口:netstat -an |findstr "端口 ...

  6. 撸了几天的sofa-tracer之后,我悟了!

    什么是分布式链路跟踪 简而言之,在分布式系统下,用于跟踪链路而衍生出的一项技术. 应用场景如下: 应用A,B,C,D,E 以一个层级关系依赖, 当用户向 应用A 发起请求,但是返回了个异常,为了排查这 ...

  7. 合肥某小公司面试题:Spring基础

    <对线面试官>系列目前已经连载25篇啦!有深度风趣的系列! [对线面试官]Java注解 [对线面试官]Java泛型 [对线面试官] Java NIO [对线面试官]Java反射 & ...

  8. .NET网页后台调用前台js方法时相同Key,调用不成功

    ClientScript.RegisterStartupScript(GetType(), "key", "<script>Save()</script ...

  9. c++实现希尔密码

    实验名称: 希尔密码的实现(c++版;本文只以26个大写英文字符作为加密后的密文的可选项) 实验原理: 引用知识: 记 Zm={0,1,2,...,m-1} 定义1:设A为定义在集合Zm 上的n阶方阵 ...

  10. Java基础篇(JVM)——字节码详解

    这是Java基础篇(JVM)的第一篇文章,本来想先说说Java类加载机制的,后来想想,JVM的作用是加载编译器编译好的字节码,并解释成机器码,那么首先应该了解字节码,然后再谈加载字节码的类加载机制似乎 ...