浅谈Redis中的RDB快照

一、概述

所谓的快照,就是记录某一个瞬间东西,比如当我们给风景拍照时,那一个瞬间的画面和信息就记录到了一张照片。

所以,RDB 快照就是记录某一个瞬间的内存数据,记录的是实际数据,而 AOF 文件记录的是命令操作的日志,而不是实际的数据。

因此在 Redis 恢复数据时, RDB 恢复数据的效率会比 AOF 快些,因为直接将 RDB 文件读入内存就可以了,不需要像 AOF 那样还需要额外执行操作命令的步骤才能恢复数据。

接下来,就来具体聊聊 RDB 快照 。

二、快照怎么用?

要熟悉一个东西,先看看怎么用是比较好的方式。

Redis 提供了两个命令来生成 RDB 文件,分别是 savebgsave,他们的区别就在于是否在「主线程」里执行:

  • 执行了 save 命令,就会在主线程生成 RDB 文件,由于和执行操作命令在同一个线程,所以如果写入 RDB 文件的时间太长,会阻塞主线程;
  • 执行了 bgsava 命令,会创建一个子进程来生成 RDB 文件,这样可以避免主线程的阻塞;

RDB 文件的加载工作是在服务器启动时自动执行的,Redis 并没有提供专门用于加载 RDB 文件的命令。

Redis 还可以通过配置文件的选项来实现每隔一段时间自动执行一次 bgsava 命令,默认会提供以下配置:

save 900 1

save 300 10

save 60 10000

别看选项名叫 sava,实际上执行的是 bgsava 命令,也就是会创建子进程来生成 RDB 快照文件。

只要满足上面条件的任意一个,就会执行 bgsava,它们的意思分别是:

  • 900 秒之内,对数据库进行了至少 1 次修改;
  • 300 秒之内,对数据库进行了至少 10 次修改;
  • 60 秒之内,对数据库进行了至少 10000 次修改。

这里提一点,Redis 的快照是全量快照,也就是说每次执行快照,都是把内存中的「所有数据」都记录到磁盘中。

所以可以认为,执行快照是一个比较重的操作,如果频率太频繁,可能会对 Redis 性能产生影响。如果频率太低,服务器故障时,丢失的数据会更多。

通常可能设置至少 5 分钟才保存一次快照,这时如果 Redis 出现宕机等情况,则意味着最多可能丢失 5 分钟数据。

这就是 RDB 快照的缺点,在服务器发生故障时,丢失的数据会比 AOF 持久化的方式更多,因为 RDB 快照是全量快照的方式,因此执行的频率不能太频繁,否则会影响 Redis 性能,而 AOF 日志可以以秒级的方式记录操作命令,所以丢失的数据就相对更少。

三、执行 bgsava 快照时,数据能被修改吗?

那问题来了,执行 bgsava 过程中,由于是交给子进程来构建 RDB 文件,主线程还是可以继续工作的,此时主线程可以修改数据吗?

如果不可以修改数据的话,那这样性能一下就降低了很多。如果可以修改数据,又是如何做到到呢?

直接说结论吧,执行 bgsava 过程中,Redis 依然可以继续处理操作命令的,也就是数据是能被修改的。

那具体如何做到到呢?关键的技术就在于写时复制技术(Copy-On-Write, COW)。

执行 bgsava 命令的时候,会通过 fork() 创建子进程,此时子进程和父进程是共享同一片内存数据的,因为创建子进程的时候,会复制父进程的页表,但是页表指向的物理内存还是一个。

只有在发生修改内存数据的情况时,物理内存才会被复制一份。

这样的目的是为了减少创建子进程时的性能损耗,从而加快创建子进程的速度,毕竟创建子进程的过程中,是会阻塞主线程的。

所以,创建 bgsave 子进程后,由于共享父进程的所有内存数据,于是就可以直接读取主线程里的内存数据,并将数据写入到 RDB 文件。

当主线程对这些共享的内存数据也都是只读操作,那么,主线程和 bgsave 子进程相互不影响。

但是,如果主线程要修改共享数据里的某一块数据(比如键值对 A)时,就会发生写时复制,于是这块数据的物理内存就会被复制一份(键值对 A'),然后主线程在这个数据副本(键值对 A')进行修改操作。与此同时,bgsave 子进程可以继续把原来的数据(键值对 A)写入到 RDB 文件。

就是这样,Redis 使用 bgsave 对当前内存中的所有数据做快照,这个操作是由 bgsave 子进程在后台完成的,执行时不会阻塞主线程,这就使得主线程同时可以修改数据。

细心的同学,肯定发现了,bgsave 快照过程中,如果主线程修改了共享数据,发生了写时复制后,RDB 快照保存的是原本的内存数据,而主线程刚修改的数据,是被办法在这一时间写入 RDB 文件的,只能交由下一次的 bgsave 快照。

所以 Redis 在使用 bgsave 快照过程中,如果主线程修改了内存数据,不管是否是共享的内存数据,RDB 快照都无法写入主线程刚修改的数据,因为此时主线程的内存数据和子线程的内存数据已经分离了,子线程写入到 RDB 文件的内存数据只能是原本的内存数据。

如果系统恰好在 RDB 快照文件创建完毕后崩溃了,那么 Redis 将会丢失主线程在快照期间修改的数据。

另外,写时复制的时候会出现这么个极端的情况。

在 Redis 执行 RDB 持久化期间,刚 fork 时,主进程和子进程共享同一物理内存,但是途中主进程处理了写操作,修改了共享内存,于是当前被修改的数据的物理内存就会被复制一份。

那么极端情况下,如果所有的共享内存都被修改,则此时的内存占用是原先的 2 倍。

所以,针对写操作多的场景,我们要留意下快照过程中内存的变化,防止内存被占满了。

四、RDB 和 AOF 合体

尽管 RDB 比 AOF 的数据恢复速度快,但是快照的频率不好把握:

如果频率太低,两次快照间一旦服务器发生宕机,就可能会比较多的数据丢失; 如果频率太高,频繁写入磁盘和创建子进程会带来额外的性能开销。

那有没有什么方法不仅有 RDB 恢复速度快的优点和,又有 AOF 丢失数据少的优点呢?

当然有,那就是将 RDB 和 AOF 合体使用,这个方法是在 Redis 4.0 提出的,该方法叫混合使用 AOF 日志和内存快照,也叫混合持久化。

如果想要开启混合持久化功能,可以在 Redis 配置文件将下面这个配置项设置成 yes:

aof-use-rdb-preamble yes

混合持久化工作在 AOF 日志重写过程。

当开启了混合持久化时,在 AOF 重写日志时,fork 出来的重写子进程会先将与主线程共享的内存数据以 RDB 方式写入到 AOF 文件,然后主线程处理的操作命令会被记录在重写缓冲区里,重写缓冲区里的增量命令会以 AOF 方式写入到 AOF 文件,写入完成后通知主进程将新的含有 RDB 格式和 AOF 格式的 AOF 文件替换旧的的 AOF 文件。

也就是说,使用了混合持久化,AOF 文件的前半部分是 RDB 格式的全量数据,后半部分是 AOF 格式的增量数据。

这样的好处在于,重启 Redis 加载数据的时候,由于前半部分是 RDB 内容,这样加载的时候速度会很快。

加载完 RDB 的内容后,才会加载后半部分的 AOF 内容,这里的内容是 Redis 后台子进程重写 AOF 期间,主线程处理的操作命令,可以使得数据更少的丢失。

以上就是浅谈Redis RDB快照的详细内容,更多关于Redis RDB的资料请关注我们其它相关文章!

(0)

相关推荐

  • Redis 通过 RDB 方式进行数据备份与还原的方法

    Intro 有的时候我们需要对 Redis 的数据进行迁移,今天介绍一下通过 RDB(快照)文件进行 Redis 数据的备份和还原 Redis 持久化 Redis 的数据持久化有两种机制,一种是 RDB(Redis Database),一种是 AOF(Append Only File) Redis 提供了不同级别的持久化方式: RDB持久化方式能够在指定的时间间隔能对你的数据进行快照存储. AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令

  • Redis打开rdb文件常用方法详解

    阿里云的redis 备份后为 rdb 文件,那么如何使用本地redis 打开rdb 文件呢? windows上操作方法整理 方法一: windows 安装的 redis 目录下,有个dump.rdb 文件 先把原来的备份,再把要打开的xxx.rdb文件命名成 dump.rdb 然后运行 redis-server.exe 就打开了 再运行 redis-cli.exe 就可以命令访问了 方法二: 在redis.windows.conf 文件中修改配置,搜索dbfilename, 把dump.rdb

  • 了解redis中RDB结构_动力节点Java学院整理

    RDB文件是在redis的"快照"的模式下才会产生,那么如果我们理解了RDB文件的结构,是不是让我们对"快照"模式能做到一个心中有数呢??? 一.RDB结构剖析 首先呢,我们要对RDB文件有一个概念性的认识,比如下面画的图一样: 从图中,我们大概看到了RDB文件的一个简要的存储模式,但为了更好的方便对照,我准备save一个empty database,对比一下看看效果: 然后我们用winHex打开dump.rdb文件,看看它的16进制. 好了,该打开的我都打开了,下

  • redis学习之RDB、AOF与复制时对过期键的处理教程

    生成RDB文件 在执行SAVE命令或者BGSAVE命令创建一个新的RDB文件时,程序会对数据库中的键进行检查,已过期的键不会被保存到新创建的RDB文件中. 举个例子,如果数据库中包含三个键k1.k2.k3,并且k2已经过期,那么当执行SAVE命令或者BGSAVE命令时,程序只会将k1和k3的数据保存到RDB文件中,而k2则会被忽略. 因此,数据库中包含过期键不会对生成新的RDB文件造成影响. 可参考rdb.c中函数rdbSave()函数源码: /* Iterate this DB writing

  • Redis持久化RDB和AOF区别详解

    RDB是Redis内存到硬盘的快照,用于redis持久化,创建RDB二进制文件,将存储在内存中的数据,持久化的放到硬盘中,当我们需要这些数据的时候,启动载入RDB文件,数据将会被存入内存中,其实RDB就是一种快照的方式持久化存储数据,也可以作为一种复制媒介,这个我们后面在谈. RDB 触发机制--主要三种方式 save 同步命令(会阻塞redis) bgsave 异步命令(fork) 自动 Save同步命令 save 文件策略:生成一个临时文件,如果存在老的文件,将会替换旧文件 bgsave 异

  • Redis两种持久化方案RDB和AOF详解

    本文主要针对Redis 有两种持久化方案RDB和AOF做了详细的分析,希望我们整理的内容能够帮助大家对这个两种方案有更加深入的理解. Redis 有两种持久化方案,RDB (Redis DataBase)和 AOF (Append Only File).如果你想快速了解和使用RDB和AOF,可以直接跳到文章底部看总结.本章节通过配置文件,触发快照的方式,恢复数据的操作,命令操作演示,优缺点来学习 Redis 的重点知识持久化. RDB 详解 RDB 是 Redis 默认的持久化方案.在指定的时间

  • 浅谈Redis中的RDB快照

    一.概述 所谓的快照,就是记录某一个瞬间东西,比如当我们给风景拍照时,那一个瞬间的画面和信息就记录到了一张照片. 所以,RDB 快照就是记录某一个瞬间的内存数据,记录的是实际数据,而 AOF 文件记录的是命令操作的日志,而不是实际的数据. 因此在 Redis 恢复数据时, RDB 恢复数据的效率会比 AOF 快些,因为直接将 RDB 文件读入内存就可以了,不需要像 AOF 那样还需要额外执行操作命令的步骤才能恢复数据. 接下来,就来具体聊聊 RDB 快照 . 二.快照怎么用? 要熟悉一个东西,先

  • 浅谈Redis中的内存淘汰策略和过期键删除策略

    目录 8种淘汰策略 过期键的删除策略 总结 redis是我们现在最常用的一个工具,帮助我们建设系统的高可用,高性能. 而且我们都知道redis是一个完全基于内存的工具,这也是redis速度快的一个原因,当我们往redis中不断缓存数据的时候,其内存总有满的时候(而且内存是很贵的东西,尽量省着点用),所以尽可能把有用的数据,或者使用频繁的数据缓存在redis中,物尽其用. 那么如果正在使用的redis内存用完了,我们应该怎么取舍redis中已存在的数据和即将要存入的数据呢,我们要怎么处理呢? re

  • 浅谈Redis 中的过期删除策略和内存淘汰机制

    目录 前言 Redis 中 key 的过期删除策略 1.定时删除 2.惰性删除 3.定期删除 Redis 中过期删除策略 从库是否会脏读主库创建的过期键 内存淘汰机制 内存淘汰触发的最大内存 有哪些内存淘汰策略 内存淘汰算法 LRU LFU 为什么数据删除后内存占用还是很高 内存碎片如何产生 碎片率的意义 如何清理内存碎片 总结 参考 前言 Redis 中的 key 设置一个过期时间,在过期时间到的时候,Redis 是如何清除这个 key 的呢? 这来分析下 Redis 中的过期删除策略和内存淘

  • 浅谈Redis 中的过期删除策略和内存淘汰机制

    目录 前言 Redis 中 key 的过期删除策略 1.定时删除 2.惰性删除 3.定期删除 Redis 中过期删除策略 从库是否会脏读主库创建的过期键 内存淘汰机制 内存淘汰触发的最大内存 有哪些内存淘汰策略 内存淘汰算法 LRU LFU 为什么数据删除后内存占用还是很高 内存碎片如何产生 碎片率的意义 如何清理内存碎片 总结 参考 前言 Redis 中的 key 设置一个过期时间,在过期时间到的时候,Redis 是如何清除这个 key 的呢? 这来分析下 Redis 中的过期删除策略和内存淘

  • 浅谈Redis中的自动过期机制

    目录 Redis中的自动过期机制 一.使用Redis Key自动过期机制 二.SpringBoot整合key失效监听 Redis中的自动过期机制 实现需求:处理订单过期自动取消,比如下单30分钟未支付自动更改订单状态 1.使用Redis Key自动过期出发事件通知2.使用定时任务30分钟后检查3.按照每分钟轮训检查 CREATE TABLE `order_number` ( `id` int(11) NOT NULL AUTO_INCREMENT, `order_name` varchar(25

  • 浅谈redis在项目中的应用

    redis在项目中的应用 ps:PHP 会自动 关redis连接 不需要手动关 对于临时的数据 可以不经过数据库直接redis上操作 /*消息队列实例 */ public function insertinfo(){ //连接本地的 Redis 服务 $redis = new \Redis(); $redis->connect('127.0.0.1', 6379); //存储数据到列表中 $infos = array('info1' => 66, 'info2' => 88); $red

  • 浅谈redis缓存在项目中的使用

    背景 Redis 是一个开源的内存数据结构存储系统. 可以作为数据库.缓存和消息中间件使用. 支持多种类型的数据结构. Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence). 通过 Redis 哨兵(Sentinel)和 Redis 集群(Cluster)的自动分区,提供高可用性(high availability). 基本数

  • 浅谈Redis缓存有哪些淘汰策略

    目录 Redis过期策略 定时删除 惰性删除 定期删除 Redis的内存淘汰机制 LRU和LFU的区别 LRU LFU Redis重启如何恢复数据呢? 总结 Redis过期策略 我们首先来了解一下Redis的内存淘汰机制. 定时删除 概述     redis默认是每隔 100ms 就随机抽取一些设置了过期时间的key,检查其是否过期,如果过期就删除.注意这里是随机抽取的.为什么要随机呢?你想一想假如 redis 存了几十万个 key ,每隔100ms就遍历所有的设置过期时间的 key 的话,就会

  • 浅谈Redis的异步机制

    目录 前言 一.Redis 的阻塞点 4 类交互对象和具体的操作之间的关系: 切片集群实例交互时的阻塞点 二.可以异步执行的阻塞点 三.异步的子线程机制 总结 前言 命令操作.系统配置.关键机制.硬件配置等会影响 Redis 的性能,不仅要知道具体的机制,尽可能避免性能异常的情况出现,还要提前准备好应对异常的方案. Redis 内部的阻塞式操作: CPU 核和 NUMA 架构的影响: Redis 关键系统配置: Redis 内存碎片: Redis 缓冲区. 一.Redis 的阻塞点 和 Redi

  • 浅谈Redis变慢的原因及排查方法

    目录 原因1:实例内存达到上限 原因2:开启内存大页 原因3:使用Swap 原因4:网络带宽过载 原因5:其他原因 原因1:实例内存达到上限 排查思路 如果你的 Redis 实例设置了内存上限 maxmemory,那么也有可能导致 Redis 变慢. 当我们把 Redis 当做纯缓存使用时,通常会给这个实例设置一个内存上限 maxmemory,然后设置一个数据淘汰策略.而当实例的内存达到了 maxmemory 后,你可能会发现,在此之后每次写入新数据,操作延迟变大了. 导致变慢的原因 当 Red

随机推荐