知道 Redis RDB 这些细节,可以少踩很多坑

2023-11-13

在使用 Redis 的过程中,你是否遇到过下面这些问题:

  • 开启 RDB 落盘,业务频繁出现请求超时。

  • 除了 save 和 bgsave 命令,还有哪些操作会触发 RDB 落盘?

  • 执行了 flushall,发现 flushall 之前写的数据又冒出来了。

  • 重启 Redis 实例之后,发现数据有丢失的情况。

带着上面这些问题,我们一起来聊聊 RDB 的一些细节。

触发 RDB 文件创建的命令有两条,save 和 bgsave。

save 我们知道会阻塞整个实例,通常也不太可能会用。

bgsave 命令是在后台生成 RDB 文件,Redis 仍然可以处理客户端请求。

但是并不能保证 bgsave 不会影响 Redis 所有的客户端请求,在生成 RDB的过程中,Redis 会 fork 出一个子进程,子进程和父进程会共享内存地址空间,可以保证子进程拥有父进程相同的内存数据。但是在 fork 子进程时,操作系统需要将父进程的内存页表复制给子进程。如果整个 Redis 实例占用的内存很大,那么它的内存页表也会很大,复制的时间也会比较长。

同时,这个过程会消耗大量的 CPU 资源,在复制完成之前,父进程也会被阻塞,无法处理客户端请求。

执行 fork 后,子进程可以扫描 Redis 中所有数据,然后将所有数据写入 RDB 文件。

之后,父进程仍然处理客户端的请求。父进程在处理写命令时,会重新分配新的内存地址空间,向操作系统申请新的内存使用,不再与子进程共享。这样,父子进程的内存会逐渐分离,父进程会申请新的内存空间并改变内存数据,子进程的内存数据不会受到影响。

可以看出,在生成RDB文件时,不仅消耗CPU资源,还需要消耗更多的内存空间。

上面也就是“开启 RDB 落盘,业务频繁出现请求超时”的原因。通常在生产环境,我们也应该避免在 master 实例上做 RDB。

那么除了 save 和 bgsave 命令,还有哪些常见会触发 RDB 呢?这里就来总结几种情况,这也是问题“除了 save 和 bgsave 命令,还有哪些操作会触发 RDB 落盘呢?”的答案:

1 配置了 RDB 落盘的情况

比如配置文件配置了 save xxx xxx,或者命令行执行了 config set save “xxx xxx”,都表示配置了 RDB 落盘。

比如配置了 save 900 1

则表示 900 秒内如果至少有 1 个 key 的值变化,则做一次 bgsave。

我们在前面有提到 bgsave 也会对客户端请求有所影响,所以不建议在 master 上增加该参数,如果为了数据备份,建议只在 slave 增加 save 参数。

2 主从复制

第一次创建主从复制关系时,会在主库执行 bgsave 命令生成 RDB 文件,然后传给从库,从库加载 RDB 文件,以完成一次全量数据的传输。

因此在业务访问高峰,并且数据量比较大的情况,不建议在 master 上创建 slave。

3 Redis 在执行 flushall 命令

配置了 RDB 落盘的情况,在执行 flushall 命令时,会进行一次 RDB 落盘,但是内容是空的。目的是将 RDB 文件也清空。

但是,如果 RDB 和 AOF 都关闭的情况下,会有下面这种情况:

127.0.0.1:6301> set aaa 111
OK
127.0.0.1:6301> set bbb 111
OK
127.0.0.1:6301> bgsave
Background saving started
127.0.0.1:6301> flushall
OK
127.0.0.1:6301> config get save
"save"
""
127.0.0.1:6301> config get appendonly
"appendonly"
"no"
127.0.0.1:6301> shutdown

再启动 Redis

127.0.0.1:6301> keys *
"aaa"
"bbb"

会看到我们清空 Redis 之前写入的数据。显然是不符合逻辑的。

这是因为在启动 Redis 时,会加载数据目录下的 RDB 文件,而这个 RDB 文件是 flushall 之前执行 bgsave 生成的,也就是会看到清空 Redis 之前写入的数据。这里也是“执行了 flushall,发现 flushall 之前写的数据又冒出来了”的原因。

所以在实例未开启 RDB 和 AOF 的情况下,如果执行 了 flushall 命令,建议再执行一次 bgsave,让 RDB 文件也清空。

另外还测试了开启 AOF,关闭 RDB 的情况:

127.0.0.1:6301> set aaa 111
OK
127.0.0.1:6301> set bbb 111
OK
127.0.0.1:6301>  bgsave
Background saving started
127.0.0.1:6301> flushall
OK
127.0.0.1:6301> config get save
"save"
""
127.0.0.1:6301> config get appendonly
"appendonly"
"yes"
127.0.0.1:6301> shutdown

启动 Redis

127.0.0.1:6301> keys *
(empty list or set)

重启之后不会再看到 flushall 之前写入的数据,因为 Redis 在 启动时加载 RDB 文件后,也会加载在执行 RDB 之后 AOF 里新增的操作。而 flushall 操作就记录在 AOF 文件中。

4 正常关闭时

我们通过在命令行执行 shutdown 正常关闭 Redis 时,并不是所有情况都会执行一次 RDB 落盘的,这里就来分析一下不同配置,重启后的情况。

4.1 AOF 和 RDB 都开启的情况

127.0.0.1:6301> set bbb 111
OK
127.0.0.1:6301> config get save
"save"
"1800 1"
127.0.0.1:6301> config get appendonly
"appendonly"
"yes"
127.0.0.1:6301> shutdown

启动 Redis

127.0.0.1:6301> get bbb
"111"

这种情况会在关闭时执行一次 RDB 落盘,启动时加载 RDB 文件,保证重启前后数据一致。

4.2 AOF 和 RDB 都未开的情况

127.0.0.1:6301> set ccc 111
OK
127.0.0.1:6301> config get save
"save"
""
127.0.0.1:6301> config get appendonly
"appendonly"
"no"
127.0.0.1:6301> shutdown

然后启动 Redis

127.0.0.1:6301> get ccc
(nil)

发现重启之前 ccc 的 key 已经丢失,因此在 master 未开启 RDB 的情况,关闭之前需要主动执行 bgsave,否则会导致数据丢失。这也是“重启 Redis 实例之后,发现数据有丢失的情况”的原因。

4.3 AOF 关闭,RDB 开启的情况

127.0.0.1:6301> set ddd 111
OK
127.0.0.1:6301> config get save
"save"
"1800 1"
127.0.0.1:6301> config get appendonly
"appendonly"
"no"
127.0.0.1:6301> shutdown

启动 Redis

127.0.0.1:6301> get ddd
"111"

这种情况会写 RDB,重启后数据未丢失。

4.4 AOF 开启,RDB 关闭的情况

127.0.0.1:6301> set eee 111
OK
127.0.0.1:6301> config get save
"save"
""
127.0.0.1:6301> config get appendonly
"appendonly"
"yes"
127.0.0.1:6301> shutdown

启动 Redis

127.0.0.1:6301> get eee
"111"

这种情况尽管不会进行 RDB 落盘,但是因为之前的操作都写入了 AOF,在 Redis 启动时,会加载 AOF 里的数据,因此也会跟关闭之前的数据保持一致。

源码附件已经打包好上传到百度云了,大家自行下载即可~

链接: https://pan.baidu.com/s/14G-bpVthImHD4eosZUNSFA?pwd=yu27
提取码: yu27
百度云链接不稳定,随时可能会失效,大家抓紧保存哈。

如果百度云链接失效了的话,请留言告诉我,我看到后会及时更新~

开源地址
码云地址:
http://github.crmeb.net/u/defu

Github 地址:
http://github.crmeb.net/u/defu

链接:https://mp.weixin.qq.com/s/RiOD50FnmbWfpHzyk5nFdA

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

知道 Redis RDB 这些细节,可以少踩很多坑 的相关文章

  • Laravel 异常队列最大尝试次数超出

    我创建了一个应用程序来向多个用户发送电子邮件 但在处理大量收件人时遇到问题 该错误出现在failed jobs table Illuminate Queue MaxAttemptsExceededException App Jobs ESe
  • 节点应用程序之间共享会话?

    我目前有两个独立的节点应用程序在两个不同的端口上运行 但共享相同的后端数据存储 我需要在两个应用程序之间共享用户会话 以便当用户通过一个应用程序登录时 他们的会话可用 并且他们似乎已登录到另一个应用程序 在本例中 它是一个面向公众的网站和一
  • MongoDB中批量FindAndModify的解决方案

    我的用例如下 我在 mongoDB 中有一组文档 我必须发送这些文档进行分析 文件格式如下 id ObjectId 517e769164702dacea7c40d8 日期 1359911127494 状态 可用 其他字段 我有一个阅读器进程
  • NoSQL(MongoDB)与 Lucene(或 Solr)作为数据库[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 随着基于文档数据库的 NoSQL 运动的发展 我最近关注了 MongoDB 我注意到如何将项目视为 文档 就像 Lucene 以及 Solr 用
  • 如何延长 django-redis 中的缓存 ttl(生存时间)?

    我正在使用 django 1 5 4 和 django redis 3 7 1 我想延长缓存的 ttl 生存时间 当我取回它时 这是示例代码 from django core cache import cache foo cache get
  • Spring Redis 排序键

    我在 Redis Spring Data Redis 中有以下键 localhost gt Keys 1 id 1 Name C5796 Site DRG1 2 id 2 Name CX1XE Site DG1 3 id 3 Name C5
  • Spring Data Redis 覆盖默认序列化器

    我正在尝试创建一个RedisTemplatebean 将具有更新的值序列化器来序列化对象JSONredis 中的格式 Configuration class RedisConfig Bean name redisTemplate Prima
  • Hector 和 Cassandra 问题 NoSuchFieldError:DEFAULT_MEMTABLE_THROUGHPUT_IN_MB

    我正在通过 Hector 测试与 Cassandra 数据库的连接 但是当我运行 Junit 测试时 我不断收到以下消息 java lang NoSuchFieldError DEFAULT MEMTABLE THROUGHPUT IN M
  • mongodb 正在运行吗?

    我已经在我的 Unix 服务器上安装了 Mongodb 和 PHP 驱动程序 我的问题是如何判断 Mongodb 是否正在运行 是否有一个简单的命令行查询来检查状态 如果我从外壳程序启动一次 如果我退出外壳程序 它会继续运行 情况似乎并非如
  • Cassandra 与 ZooKeeper 的事务 - 这有效吗?

    我正在尝试在 ZooKeeper 的帮助下为 Cassandra 实现一个事务系统 由于我认为我在数据库实现方面没有足够的经验 所以我想知道我的想法原则上是否可行 或者是否有任何重大缺陷 以下是步骤的高级描述 识别所有要编辑的行 键 和列
  • 批量将Dictionary中的数据设置到Redis中

    我正在使用 StackExchange Redis DB 插入键值对字典Batch如下 private static StackExchange Redis IDatabase database public void SetAll
  • 为什么我们需要 Redis 来运行 CKAN?

    我想知道为什么我们需要 Redis 服务器来运行 CKAN 如果需要 为什么 我如何使用 CKAN 配置它 附注 我正在 RHEL7 中运行我的 ckan 实例 Update Redis 已成为一项要求从CKAN 2 7开始 https d
  • 在 Rails 应用程序上将 HASH 保存到 Redis

    我刚刚开始使用 Redis 和 Rails 所以这可能是一个愚蠢的问题 我试图将哈希值保存到 Redis 服务器 但是当我检索它时 它只是一个字符串 IE hash field gt value field2 gt value2 redis
  • JedisPoolConfig 不可分配给 GenericObjectPoolConfig

    我有一个基于 Spring 的 Java Web 应用程序托管在 Heroku 上 我正在尝试使用 Redis 实现来利用 Spring 缓存抽象 当服务器启动时 我收到一条错误消息 Type redis clients jedis Jed
  • MongoDb聚合

    如何使用 mongoDb 聚合编写模拟查询 select count as ccount from a group by a someField order by ccount desc limit 1 使用 mongoDb 中的 grou
  • Redis AOF fsync(始终)与 LSM 树

    我对日志结构化合并树 LSM 树 的理解是 它利用了附加到磁盘非常快 因为它不需要查找 这一事实 只需将更新附加到预写日志并返回到客户端即可 我的理解是 这仍然提供了立即的持久性 同时仍然非常快 我不认为 Redis 使用 LSM 树 它似
  • 为什么 NoSQL 比 RDBMS 更擅长“横向扩展”?

    我在a中读过以下文字技术博客 http tekedia com 12083 nosql database advantages and disadvantages 讨论NoSQL的优缺点 多年来 为了提高数据库服务器的性能 数据库管理员不得
  • spring中如何使用jackson代替JdkSerializationRedisSerializer

    我在我的一个 Java 应用程序中使用 Redis 并且正在序列化要存储在 Redis 中的对象列表 但是 我注意到使用 RedisTemplate 会使用 JdkSerializationRedisSerializer 相反 我想使用 J
  • 为什么Redis SET性能优于GET?

    根据Redis基准 http redis io topics benchmarkss Redis 可以执行 100 000 SET 操作 秒和 80 000 GET 操作 秒 Redis 是一种内存数据库 这似乎令人惊讶 因为通常人们会认为
  • 如何按键中的值对 Redis 哈希进行排序

    Redis 有没有一种好方法来获取按值排序的哈希中的键 我查看了文档 但没有找到直接的方法 另外有人可以解释一下redis中的排序是如何实现的 以及什么吗 本文档 http redis io commands SORT using hash

随机推荐

  • 小程序的点击复制功能和长按复制功能

    前言 在小程序中实现点击复制功能和长按复制功能 主要使用wx setClipboardData 小程序的复制功能 官方方法 wx setClipboardData 小程序的复制功能 功能描述 设置系统剪贴板的内容 调用成功后 会弹出 toa
  • SpringBoot:返回响应,统一封装

    说明 接口的返回响应 封装成统一的数据格式 再返回给前端 返回响应 统一封装实体 数据结构如下 代码 package com example core model import io swagger v3 oas annotations m
  • 官网下载git缓慢问题

    问题描述 为上传项目到github git就避免不了需要下载 但是在git官网中下载 1 2kb s的速度 中途还会卡顿 解决方案 在腾讯软件中心下载 几分钟方可下载完成 1 电脑上有电脑管家的话 选择软件管理 搜索git就可以下载 2 直
  • MBR2GPT:将 MBR 转换为 GPT

    几年前 Windows操作系统通常安装在主引导记录 MBR 分区上 但是 随着固件 UEFI 和更大磁盘的安全进步 现在需要 GUID 分区表 GPT 磁盘来利用这些新功能 如果您将系统磁盘配置为 MBR 磁盘 则MB42GPT exe实用
  • logistic回归详解一:为什么要使用logistic函数

    项目github地址 bitcarmanlee easy algorithm interview and practice 欢迎大家star 留言 一起学习进步 从线性分类器谈起 给定一些数据集合 他们分别属于两个不同的类别 例如对于广告数
  • php 判断数组里有大于0 的值_如何比较两个PHP多维数组

    点击蓝字关注我们 每天获取最新的编程小知识 源 php中文网 源 www php cn 判断两个多维数组是否相等 或有哪些元素区别 我们可以通过PHP中array udiff 函数和create function 方法 strcmp 等函数
  • C++ map

    定义一个map对象 map
  • python求水仙花数(用列表生成式)

    水仙花数是指一个n位数 n 3 它的每位上的数字的n次幕之和等于它本身 例如 13 53 3 3 153 求100 999之间所有的水仙花数 i for i in range 100 1000 if i 100 3 i 10 10 3 i
  • LetCode#7给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后结果。 如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。JAVA

    每天一道算法题 拒绝当懒狗 一起进步 题目 给你一个 32 位的有符号整数 x 返回将 x 中的数字部分反转后的结果 如果反转后整数超过 32 位的有符号整数的范围 231 231 1 就返回 0 假设环境不允许存储 64 位整数 有符号或
  • MySQL 可重复读隔离级别,完全解决幻读了吗?

    我在上一篇文章中提到 MySQL InnoDB 引擎的默认隔离级别虽然是 可重复读 但是它很大程度上避免幻读现象 并不是完全解决了 解决的方案有两种 针对快照读 普通 select 语句 是通过 MVCC 方式解决了幻读 因为可重复读隔离级
  • 通过URL自动触发Jenkins构建任务

    方法一 进入jenkins安全设置 开启安全域及授权策略 2 在用户设置处生成api token 复制生成的token 3 选择测试项目 配置 构建触发器 选择触发远程构建 将token粘贴在身份验证令牌处 保存 4 在浏览器中输入 htt
  • 联想ideapad700-15isk(小新线下版)黑苹果完美驱动附详细安装过程

    直接上安装的流程 欢迎大家关注我的个人博客 联想ideapad700 15isk 我的配置如下 前期准备 制作安装盘 盘符分配 设置U盘启动 开始安装 添加本地引导 安装完成进入设置 关于clover 划重点 2020年8月30日更新 20
  • ssm框架+Layui整合案例

    业余写得整合案例 想学习的可以来参考 初来乍到 准备工作 Layui tomcat mysql 目录 1 实现的效果图 2 实现代码 2 0 前端代码 2 1 登录页面login jsp 2 2 登录后跳转的主页面 main jap web
  • SQLi LABS Less-22

    第22关使用POST请求提交参数 对账号和密码中的特殊字符执行了转译的操作 难度较大 这一关的重点在于Cookie 用户登录成功后 将base64编码后的用户名保存到Cookie中 点击提交按钮时 会从Cookie中获取用户名 使用base
  • Yum update和upgrade的区别

    Yum update和upgrade的区别 Linux yum中package升级命令有两个分别是 yum upgrade 和 yum update 1 区别 默认情况下 yum update和yum upgrade的功能是完全一样的 都是
  • 基于.NET CORE 3.1的WEB API通过EF CORE连接MySQL

    基于 NET CORE 3 1的WEB API通过EF CORE连接MySQL 注 本文不采用CodeFirst 不使用迁移 1 准备好一个WEB API项目 可以看我之前的文章 2 准备好一个MySQL数据库并创建表 3 引用nuget包
  • 神经网络学习小记录44——训练资源汇总贴

    神经网络学习小记录44 训练资源汇总贴 前言 权值文件 1 迁移学习 传统神经网络 2 目标检测 a keras权重 b pytorch权重 c tensorflow2权重 3 实例分割 4 语义分割 旧版 5 语义分割 新版 a kera
  • nginx请求返回html文件,nginx返回json或者文本格式的方法

    用nginx怎么返回json格式或者文本格式的数据 其实很简单 如下代码 1 返回文本格式 location get text default type text html return 200 hello world 2 返回json格式
  • sublime配置go环境_Win10下sublime text3搭建go语言开发环境--工具篇

    进行 go 语言开发环境的搭建 最近进行了大量的搜索 因为在搭建的过程中遇到了挺多的问题 先介绍搭建的环境 系统 Win10 IDE sublime text3 相关插件 GoSublime 这篇文会介绍如下几个部分 1 下载Golang
  • 知道 Redis RDB 这些细节,可以少踩很多坑

    在使用 Redis 的过程中 你是否遇到过下面这些问题 开启 RDB 落盘 业务频繁出现请求超时 除了 save 和 bgsave 命令 还有哪些操作会触发 RDB 落盘 执行了 flushall 发现 flushall 之前写的数据又冒出