[Redis#14] 持久化 | RDB | bgsave | check-rdb | 灾备

目录

0.概述

持久化的策略

[1 RDB](#1 RDB)

[1.1 触发机制](#1.1 触发机制)

[1.2 流程说明](#1.2 流程说明)

[1.3 RDB 的优缺点](#1.3 RDB 的优缺点)


0.概述

  • 在学习 MySQL 数据库时,我们了解到事务的四个核心特性:原子性、一致性、持久性和隔离性。
  • 这些特性确保了数据库操作的安全性和可靠性。当我们转向 Redis 时,尽管它主要将数据存储在内存中,但为了保证数据的持久性,Redis 也提供了几种机制来将数据保存到硬盘上。
  • 硬盘上的数据主要用于 Redis 重启后恢复数据。
  • 当向 Redis 中插入数据时,需要同时考虑如何将数据写入内存和硬盘。为此,Redis 提现了两种不同的持久化策略:RDB(Redis Database)模式与 AOF(Append Only File)模式。
持久化的策略
  • RDB 模式 :采取定期备份的方式,即每隔一段时间,就会把内存中的所有数据备份到硬盘上。这种方式适合用于冷备和主从复制场景。
  • AOF 模式 :采用实时备份的方法,每当内存中有新的数据变动时,都会立即追加记录到硬盘上的日志文件中。这种方法提供了更好的数据完整性保障,但在性能上可能不如 RDB 方式。

通过这两种方式,Redis 能够有效地平衡数据安全性和系统性能,让用户可以根据实际需求选择最合适的持久化方案。


相对来说,一台电脑上,硬盘是最容易坏的部分。

  • CPU? 如果你把CPU用坏了,恭喜你,可以去买彩票了(bush
  • 显卡? 除非你是高强度挖矿(矿卡)
    • "挖矿"是用电脑的算力去解复杂的数学问题,来获取虚拟货币的过程。
    • 以比特币为例,它的交易记录保存在区块链中,"挖矿"就是矿工通过计算机运算来竞争记账权,成功就能获得比特币奖励。这一过程需要强大的计算能力,会消耗大量能源。
    • "矿卡"是指用于挖矿的显卡。因为长时间高负荷工作,矿卡的使用寿命会缩短,性能也可能下降。
    • 和普通显卡相比,矿卡的硬件老化和损坏程度更严重。
  • 内存? 概率非常低
  • 硬盘 反而是最容易出问题的,尤其是"机械硬盘"。

持久化到硬盘,有同学就会想,那硬盘坏了怎么办?对于重要资料,我们可以再拿另一块移动硬盘,来作为备份用的硬盘

本篇主要内容:

  • 介绍 RDB、AOF 的配置和运行流程,以及控制持久化的命令,如 bgsave 和 bgrewriteaof。
  • 对常见持久化问题进行分析定位和优化。

1 RDB

RDB 持久化是把当前进程数据生成 快照 保存到硬盘的过程,触发 RDB 持久化过程分为 手动触发和自动触发。

  • 何为生成快照,就像警察来到案发现场一样,++对没有破坏的案发现场进行拍照,按照照片上提供的线索对现场当时的情况进行还原.++
  • Redis生成快照的方式也是类似的,Redis在内存中存储数据之后,Redis会给这些数据进行"拍照",生成一个文件,存储在硬盘中.后续在Redis重启之后,就可以根据刚才生成的快照,把内存中的数据进行恢复处理.
1.1 触发机制

手动触发分别对应 save 和 bgsave 命令:

  • save 命令 :执行的时候,Redis就会全力以赴的进行"快照生成"操作,此时就会阻塞Redis的其他客户端的命令,结果类似与keys *,所以我们一般不建议使用save命令.
  • bgsave 命令 :不会阻塞影响到其他的Redis客户端, 是由于Redis引入了多进程的方式来实现这个功能. 其中一个进程负责继续接收客户端的请求, 另一个进程负责生成快照并存储到硬盘中. 也就是Redis会创建出一个子进程,子进程会完成持久化操作. 持久化会把数据写入到新的文件中, 然后使用新的文件替换旧的文件.

Redis 内部的所有涉及 RDB 的操作都采用类似 bgsave 的方式。

关于文件是否被替换,我们可以使用Linux的stat命令来查看文件的iNode编号.在执行bgsave命令之后,我们发现文件的iNode有变化.


1.2 流程说明

bgsave 是主流的 RDB 持久化方式

当用户执行 bgsave 命令时,Redis 会通过以下步骤生成数据快照:

  • 创建子进程
    • 父进程通过 fork 系统调用创建一个子进程。
    • fork 是 Linux 的系统调用,因为 Redis 只支持在 Linux 上运行,所以直接使用了这个系统调用。
    • 执行 fork 时,父进程的所有资源(包括内存中的数据、进程地址空间、页表和 PCB 等)都会被复制一份给子进程。
  • 子进程生成快照
    • 子进程负责生成数据快照。
    • 父进程继续响应其他命令,不会被阻塞。
  • 信号通知
    • 当子进程完成快照生成后,会发送一个信号给父进程,通知其快照已经完成。实现 新旧文件替换
    • 如果父进程在收到信号之前收到了另一个 bgsave 命令,它会直接返回而不处理,因为已经有子进程正在执行持久化操作。这样可以确保多个 bgsave 命令只触发一次持久化操作。

流程

  • Fork:创建子进程,使用写时拷贝机制。
  • 生成 RDB 文件:子进程将内存数据写入临时文件
  • 替换文件 :子进程将临时文件重命名为 dump.rdb,这是一个原子操作。
  • 通知父进程:子进程通过信号通知父进程持久化完成。

问题: 搜的当中还是没有解释,关于 子进程rdb文件的生成 是否是一个写时拷贝的操作,问了一下ai,只说到了修改会 写时拷贝

总结

  • bgsave命令 :通过 fork 创建子进程来生成数据快照,父进程继续响应其他命令。
  • 写时拷贝fork 时并不立即复制所有内存数据,而是采用 写时拷贝**(Copy-on-Write, COW)** 技术 只有在实际写入时才进行拷贝,从而提高效率并节省内存空间。

下面我们来查看执行bgsave前后两次的iNode.

查看

可以发现 bgsave 后,inode 发生了变化,说明 存在 子进程 & 新旧文件替换

而 save命令是直接在之前的旧文件上写入数据, 所以在执行save命令之后, dump.rdb文件的iNode不会改变

❓斯 理论来说是上面这样不会变化的,可是实验发现 inode 变了,为什么呢,博主也还在思考,感觉可能是因为 其他外部因素的影响,使文件被删除并重新创建了

✔️已解决)之前网上搜到的大部分资料, 都是说 save 命令没有创建新文件, 直接写旧文件. 但是翻下源码, 确实是创建新文件的. 这个可能和redis 版本有关, 可能早期版本是直接写的, 导致网上很多资料说的都是早期的情况吧.

rdb.c 的 rdbSave 函数里可以看到这个过程


下面我们来对bgsave的实际效果进行展示:

1. 手动触发

如果我们不使用 bgsave, 用kill -9命令直接终止Redis相关进程, 再次进入,数据直接丢失.

2. 自动触发

除了手动触发之外,Redis 运行自动触发 RDB 持久化机制,这个触发机制才是在实战中有价值的。

  • 使用 save 配置。如 "save m n" 表示 m 秒内数据集发生了 n 次修改,自动 RDB 持久化。
  • 从节点进行全量复制操作时,主节点自动进行 RDB 持久化,随后将 RDB 文件内容发送给从节点。
  • 执行 shutdown 命令关闭 Redis 时,执行 RDB 持久化。

a. save 配置

RDB快照的生成是定期生成,所以我们可以在Redis的配置文件中设置让Redis每隔多长时间就触发一次 .其中的配置项是save配置项.

可以 cd /ect/redis 中 nano redis.conf ctrl+w save 查看到

例如:save 900 1

  • 如果在900秒之内 且 只有1个键值对的修改,那么就是没900秒触发一次.
  • 以此类推.当我们把save配置项设置为一个空字符串("")的时候,这时候就会 关闭快照的定期自动生成.

Redis 的 RDB(Redis Database Backup)持久化机制是通过在指定的时间间隔内生成内存数据的快照来实现的。尽管RDB文件中的参数可以按需调整,但有一个基本原则:由于生成一次RDB快照成本较高,不应过于频繁地执行此操作。

  • 这意味着,在两次RDB快照之间,如果发生了大量键值对的变化或服务突然崩溃,可能会导致部分数据丢失。
  • 例如,假设在12点时生成了RDB快照,而从12:01开始直到下一次快照生成前,Redis接收到大量的键更新请求。若在此期间Redis服务发生故障,则12点之后的所有更改将无法恢复。
  • 例如:单机游戏 利用读档和存档的时间 bug 可以不停抽奖,直到抽到想要的- SL 大法(save&load)

下篇文章 我们将学到 AOF 就是解决 这种情况的

redis生成的RDB文件存放在Redis的工作目录中,其中有一个dump.rdb文件.这个是Redis的RDB机制生成的镜像文件,Redis服务器就是默认开启了RDB的.这个文件就是RDB保存在硬盘中的持久化文件.

  • RDB文件存放位置 :默认情况下,RDB文件存放在Redis的工作目录中,通常为/var/lib/redis/。可以通过配置文件中的dir选项来修改这个路径。

  • RDB文件名 :默认文件名为dump.rdb,可通过配置文件中的dbfilename项进行自定义。

  • RDB文件性质 :这是一个二进制文件,它以压缩形式保存内存中的数据,虽然会占用一定的CPU资源,但能有效节省硬盘空间。

  • RDB文件重要性 :由于RDB文件直接关系到Redis的数据持久化,因此不建议随意修改该文件。如果文件损坏,Redis可能无法正常启动,或者即使启动成功,数据也可能与预期不符。

  • RDB文件检查工具 :为了确保RDB文件的完整性,Redis提供了一个检查工具redis-check-rdb <rdb文件路径>,用于检测文件是否损坏。

正确配置和管理 RDB快照对于保证Redis数据的安全性和一致性至关重要。同时,合理设置快照生成频率,既能避免过多消耗系统资源,又能有效减少因服务异常导致的数据损失风险。


补充

RDB 文件损坏的影响

  • 手动损坏 RDB 文件
    • 如果手动修改 RDB 文件内容,可能会导致文件损坏。
    • 重启 Redis 服务器时,Redis 会尝试重新加载 RDB 文件。
    • 如果文件损坏,Redis 可能无法正常启动。
  • RDB 文件损坏的后果
    • 如果 RDB 文件损坏,Redis 服务器可能会启动失败。
    • 具体影响取决于损坏的位置:
      • 文件末尾损坏:对前面的内容影响较小。
      • 中间位置损坏:可能导致 Redis 服务器无法启动。
  • 日志检查
    • 当 Redis 服务器启动失败时,可以通过查看 Redis 日志来了解具体原因。

    • 日志文件通常位于 /var/log/redis/ 目录下,可以通过以下命令查看:

      cd /var/log/redis/

    • 日志文件示例:

      rw-rw---- 1 redis adm 83674 11:29 redis-server.log
      rw-rw---- 1 redis adm 3405 16:22 redis-server.log.1.gz

  • 错误信息

    • 如果 RDB 文件损坏,Redis 日志中可能会出现以下错误信息:

      Short read or OOM loading DB: Unrecoverable error, aborting now.
      Internal error in RDB reading function at rdb.c:2125 -- Unexpected EOF reading RDB file

  • 上述错误信息 可以 通过 redis-check-rdb 检测后再来启动来检查

我们来查看一下


1.3 RDB 的优缺点

优点

  • RDB是⼀个紧凑压缩的⼆进制⽂件 ,代表Redis在某个时间点上的数据快照,⾮常适⽤于备份,全量复制等场景
    • 例如 :每6⼩时执⾏bgsave备份,并把RDB ⽂件复制到远程机器或者⽂件系统(如 hdfs)⽤于灾备
  • Redis加载RDB恢复数据远远快于AOF的方式
    • RDB以二进制的方式来组织数据,直接把数据读取到内存中,按照字节的格式取出来,放到结构体/对象中即可
    • AOF使用文本的方式来组织数据,需要进行一系列的字符串切分操作

缺点

  • RDB⽅式数据没办法做到实时持久化 / 秒级持久化 ,因为bgsave每次运⾏都要执⾏fork创建⼦进程,属于重量级操作,频繁执⾏成本过⾼
  • RDB ⽂件使⽤特定⼆进制格式保存,Redis 版本演进过程中有多个 RDB 版本,兼容性可能有⻛险
相关推荐
LKAI.29 分钟前
搭建Elastic search群集
linux·运维·elasticsearch·搜索引擎
gywl2 小时前
openEuler VM虚拟机操作(期末考试)
linux·服务器·网络·windows·http·centos
青木沐2 小时前
Jenkins介绍
运维·jenkins
WTT00113 小时前
2024楚慧杯WP
大数据·运维·网络·安全·web安全·ctf
苹果醋33 小时前
React源码02 - 基础知识 React API 一览
java·运维·spring boot·mysql·nginx
日记跟新中3 小时前
Ubuntu20.04 修改root密码
linux·运维·服务器
唐小旭4 小时前
服务器建立-错误:pyenv环境建立后python版本不对
运维·服务器·python
码农君莫笑4 小时前
信管通低代码信息管理系统应用平台
linux·数据库·windows·低代码·c#·.net·visual studio
明 庭4 小时前
Ubuntu下通过Docker部署NGINX服务器
服务器·ubuntu·docker