大家都知道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. deeplearning模型分析

    deeplearning模型分析 FLOPs paddleslim.analysis.flops(program, detail=False) 获得指定网络的浮点运算次数(FLOPs). 参数: pr ...

  2. YOLO v1到YOLO v4(上)

    YOLO v1到YOLO v4(上) 一.  YOLO v1 这是继RCNN,fast-RCNN和faster-RCNN之后,rbg(RossGirshick)针对DL目标检测速度问题提出的另外一种框 ...

  3. NVIDIA Tensor Cores解析

    NVIDIA Tensor Cores解析 高性能计算机和人工智能前所未有的加速 Tensor Cores支持混合精度计算,动态调整计算以加快吞吐量,同时保持精度.最新一代将这些加速功能扩展到各种工作 ...

  4. NVIDIA FFmpeg 转码技术分析

    NVIDIA FFmpeg 转码技术分析 所有从 Kepler 一代开始的 NVIDIA GPUs 都支持完全加速的硬件视频编码,而从费米一代开始的所有 GPUs 都支持完全加速的硬件视频解码.截至 ...

  5. SQL Parameter参数的用法

    SqlParameter 类 表示 SqlCommand 的参数,也可以是它到 DataSet 列的映射. 无法继承此类. 命名空间:  System.Data.SqlClient 程序集:  Sys ...

  6. .NET平台系列27:在 Linux 上安装 .NET Core/.NET5/.NET6

    系列目录     [已更新最新开发文章,点击查看详细] .NET 在不同的 Linux 发行版上可用. 大多数 Linux 平台和发行版每年都有一个主要版本,并提供用于安装 .NET 的包管理器. 本 ...

  7. bzoj2427 软件安装! 树dp

    软件安装 内存限制:128 MiB 时间限制:1000 ms 标准输入输出     题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一 些软 ...

  8. TestNG 组测试

    方法分组测试 1. 给@Test注解后面加groups参数,如 @Test(groups = "groupa") 2. 可以添加@BeforeGroups和@AfterGroups ...

  9. B站英文教学视频的字幕获取 学习必看!

    前言 最近在B站看一些纯英文的课程,视频课程有的是纯中文字幕的,有的是纯英文字幕的.由于英文的重要性,一份字幕的文档在我们观看后,留着日后粗略再读是很有益处的.但是为了得到这个英文字幕走了许多弯路.最 ...

  10. 5.1 万 Star!不用 root 就能连接控制安卓的开源工具

    [导语]:一款在 PC 端控制安卓设备的小工具.可在 PC 和安卓设备间互通剪贴板.用电脑键盘打字.传输文件.安装程序.截图.录屏等等功能. 简介 scrcpy 可以显示并控制通过 USB (或 TC ...