Redis的持久化

本文详细介绍了Redis的RDB和AOF两种持久化机制,包括它们的触发条件、工作流程、优缺点以及文件处理策略。重点讲解了RDB的自动触发、文件生成和AOF的文本协议、重写机制及文件校验等内容。
摘要由CSDN通过智能技术生成

简介

Redis 支 持 RDB 和 AOF 两 种 持 久 化 机 制 , 持 久 化 功 能 有 效 地 避 免 因 进 程 退 出 造 成 的 数 据 丢 失 问 题 , 当 下 次 重 启 时 利 用 之 前 持 久 化 的 文 件 即 可 实 现 数 据 恢 复 。

1.RDB

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

1.1触发机制

  • 手动触发 RDB 的 持 久 化 机 制
    手动触发分别对应save和bgsave命令:
    (1)save 命 令 : 阻 塞 当 前 Redis 服 务 器 , 直 到 RDB 过 程 完 成 为 止 , 对 于 内 存 比 较 大 的 实 例 会 造 成 长 时 间 阻 塞 , 线 上 环 境 不 建 议 使 用 。
    运 行 save 命 令 对 应 的 Redis 日 志 如 下 :

    * DB saved on disk
    

    (2)bgsave 命 令 : Redis 进 程 执 行 k 操 作 创 建 子 进 程 , RDB 持 久 化 过 程 由 子 进 程 负 责 , 完 成 后 自 动 结 束 。 阻 塞 只 发 生 在 k 阶 段 , 一 般 时 间 很 短 。
    运 行 bgsave 命 令 对 应 的 Redis 日 志 如 下 :

    * Background saving started by pid 29
    * DB saved on disk
    * Fork CoW for RDB: current 0 MB, peak 0 MB, average 0 MB
    * Background saving terminated with success
    

    显 然 bgsave 命 令 是 针 对 save 阻 塞 问 题 做 的 优 化 。 因 此 Redis 内 部 所 有 的 涉 及RDB的 操 作 都 采 用 bgave 的 方 式 , 而 save 命 令 己 经 废 弃 。

  • 自 动 触 发 RDB 的 持 久 化 机 制
    (1) 使 用 save 相 关 配 置 , 如 “save m n”。 表 示 m 秒 内 数 据 集 存 在 n 次 修 改 时 , 自 动 触 发 bgsave。
    (2) 如 果 从 节 点 执 行 全 量 复 制 操 作 , 主 节 点 自 动 执 行 bgsave 生 成 RDB 文件并发送给从节点。
    (3) 执 行 debug reload 命 令 重 新 加 载 Redis 时 , 也 会 自 动 触 发 save 操 作 。
    (4) 默 认 情 况 下 执 行 shutdown 命 令 时 , 如 果 没 有 开 启 AOF 持 久 化 功 能 则 自 动 执 行 bgsave 。

1.2流程说明

bgsave是主流的触发RDB持久化的方式,根据下图来了解它的运作流程:
在这里插入图片描述流程如下:

(1) 执 行 bgsave 命 令,Redis父进程判断当前是否存在正在执行 的 子进 程 , 如 RDB/AOF 子 进 程 ,如果存在bgsave命令直接返回 。

(2) 父 进 程 执 行fork 操 作 创 建 子 进 程 ,fork 操 作 过 程 中 父 进 程 会 阻 塞 , 通 过 info stats 命 令 查 看 latest_fork_usec 选项 ,可以获取最近一个fork操作的耗时 ,单位为微秒 。
在这里插入图片描述(3) 父进程 fork完成后,bgsave 命令返 回 “Background saving started” 信 息 并 不 再 阻 塞 父 进 程 ,可以继续响应其他命令 。
(4) 子 进 程 创 建 RDB 文 件 ,根 据父进程内存生成临时快照文件 ,完 成 后 对 原 有 文 件 进 行 原 子 替 换 。执行lastsave命令可以获取最后一次生成 RDB 的 时 间 , 对 应info统计的 rdb_Iast_save_time 选 项 。

127.0.0.1:6379> lastsave
(integer) 1698376643
127.0.0.1:6379> info
# Persistence
rdb_last_save_time:1698376643
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:0
rdb_current_bgsave_time_sec:-1
rdb_saves:2
rdb_last_cow_size:839680
rdb_last_load_keys_expired:1
rdb_last_load_keys_loaded:34

(5) 进 程 发 送 信 号 给 父 进 程 表 示 完 成 , 父 进 程 更 新 统 计 信 息 , 具 体 见 info persistence 下 的 rdb_* 相 关 选 项 。

1.3RDB文件的处理

  • 保存
    RDB 文 件 保 存 在 dir 配 置 指 定 的 目 录 下 , 文 件 名 通 过 dbfilename 配 置 指 定 。 可 以 通 过 执 行 config set dir{newDir} 和 config set dbfilename{newFileName} 运 行 期 动 态 执 行 , 当 下 次 运 行 时 RDB 文 件 会 保 存 到 新 目 录 。
    当 遇 到 坏 盘 或 磁 盘 写 满 等 情 况 时 , 可 以 通 过 config set dir{newDir} 在 线 修 改 文 件 路 径 到 可 用 的 磁 盘 路 径 , 之 后 执 行 bgave 进 行 磁 盘 切 换 , 同 样 适 用 于 AOF 持 久 化 文 件 。
  • 压缩
    Redis 默 认 采 用 LZF 算 法 对 生 成 的 RDB 文 件 做 压 缩 处 理 , 压 缩 后 的 文 件 远 远 小 于 内 存 大 小 , 默 认 开 启 , 可 以 通 过 参 数 config set rdbcompression{yes|no}动 态 修 改 。
    虽 然 压 缩 RDB 会 消 耗 CPU , 但 可 大 幅 降 低 文 件 的 体 积 , 方 便 保 存 到 硬 盘 或 通 过 网 络 发 送 给 从 节 点 , 因 此 线 上 建 议 开 启 。
  • 校验
    如 果 Redis 加 载 损 坏 的 RDB 文 件 时 拒 绝 启 动 , 并 打 印 如 下 日 志 :
    #Short read or OOM loading DB. Unrecoverable error,aborting now.
    这时可以使用Redis提供的redis-check-dump工具校验RDB文件并获取对应的错误报告。

1.4RDB的优缺点

  • RDB的优点
    (1)RDB 是 一 个 紧 凑 压 缩 的 二 进 制 文 件 , 代 表 Redis 在 某 个 时 间 点 上 的 数 据 快 照 。 非 常 适 用 于 备 份 , 全 量 复 制 等 场 景 。 比 如 每 6 小 时 执 行 bgsave 备 份 , 并 把 RDB 文 件 拷 贝 到 远 程 机 器 或 者 文 件 系 统 中 ( 如 hdfs) , 用 于 灾 难 恢 复 。
    (2)Redis 加 载 RDB 恢 复 数 据 远 远 快 于 AOF 的 方 式 。
  • RDB的缺点
    (1)RDB 方 式 数 据 没 办 法 做 到 实 时 持 久 化 / 秒 级 持 久 化 。 因 为 bgsave 每 次 运 行 都 要 执 行 fork 操 作 创 建 子 进 程 , 属 于 重 量 级 操 作 , 频 繁 执 行 成 本 过 高 。
    (2)RDB 文 件 使 用 特 定 二 进 制 格 式 保 存 , Redis 版 本 演 进 过 程 中 有 多 个 格 式 的 RDB 版 本 , 存 在 老 版 本 Redis 服 务 无 法 兼 容 新 版 RDB 格 式 的 问 题 。
    (3)针 对 RDB 不 适 合 实 时 持 久 化 的 问 题 , Redis 提 供 了 AOF 持 久 化 方 式 来 解 决 。

2.AOF

AOF ( append only file ) 持 久 化 : 以 独 立 日 志 的 方 式 记 录 每 次 写 命 令 , 重 启 时 再 重 新 执 行 AOF 文 件 中 的 命 令 达 到 恢 复 数 据 的 目 的 。 AOF 的 主 要 作 用 是 解 决 了 数 据 持 久 化 的 实 时 性 , 目 前 己 经 是 Redis 持 久 化 的 主 流 方 式 。 理 解 掌 握 好 AOF 持 久 化 机 制 对 我 们 兼 顾 数 据 安 全 性 和 性 能 非 常 有 帮 助 。

2.1使用AOF

开 启 AOF 功 能 需 要 在redis.conf文件中设 置 配 置 : appendonly yes , 默 认 不 开 启 。 AOF 文 件 名 通 过 appendfilename 配 置 设 置 , 默 认 文 件 名 是 appendonly.aof。 保 存 路 径 同 RDB 持 久 化 方 式 一 致 , 通 过 dir 配 置 指 定 。 AOF 的 工 作 流 程 操 作 : 命 令 写 入 ( append) 、 文 件 同 步 (sync) 、 文 件 重 写 (rewrite ) 、 重 启 加 载 (load) , 如 图 所 示 。
在这里插入图片描述流程如下:
(1) 所 有 的 写 入 命 令 会 追 加 到 aof_buf ( 缓 冲 区 ) 中 。
(2)AOF 缓 冲 区 根 据 对 应 的 策 略 向 硬 盘 做 同 步 操 作 。
(3)随 着 AOF 文 件 越 来 越 大 , 需 要 定 期 对 AOF 文 件 进 行 重 写 , 达 到 压 缩 的 目 的 。
(4)当 Redis 服 务 器 重 启 时 , 可 以 加 载 AOF 文 件 进 行 数 据 恢 复 。

了解AOF工作流程之后,下面针对每个步骤做详细介绍。

2.2命令写入

AOF命令写入的内容直接是文本协议格式。例如set hello world这条命令,在AOF缓冲区会追加如下文本:

*3\r\n$3\r\nset\r\n$5\r\nhello\r\n$5\r\nworld\r\n

关于AOF的两个疑惑:

  • AOF为什么直接采用文本协议格式?
    1.文本协议具有很好的兼容性。
    2.开启AOF后,所有写入命令都包含追加操作,直接采用协议格式,避免了二次处理开销。
    3.文本协议具有可读性,方便直接修改和处理。
  • AOF为什么把命令追加到aof_buf中?
    Redis使用单线程响应命令,如果每次写AOF文件命令都直接追加到硬盘,那么性能完全取决于当前硬盘负载。先写入缓冲区aof_buf中,还有另一个好处,Redis可以提供多种缓冲区同步硬盘的策略,在性能和安全性方面做出平衡。

2.3文件同步

Redis提供了多种AOF缓冲区同步文件策略,由参数appendfsync控制,不同值的含义如表所示。
在这里插入图片描述

  • 配置为always时,每次写入都要同步AOF文件,在一般的SATA硬盘上,Redis只能支持大约几百TPS写入,显然跟Redis高性能特性背道而驰,不建议配置。
  • 配置为no,由于操作系统每次同步AOF文件的周期不可控,而且会加大每次同步硬盘的数据量,虽然提升了性能,但数据安全性无法保证。
  • 配置为everysec,是建议的同步策略,也是默认配置,做到兼顾性能和数据安全性。

2.4重写机制

随着命令不断写入AOF,文件会越来越大,为了解决这个问题,Redis引入AOF重写机制压缩文件体积。AOF文件重写是把Redis进程内的数据转化为写命令同步到新AOF文件的过程。AOF重写运作流程如下图:
在这里插入图片描述流程说明:
(1)执行AOF重写请求。
(2)父进程执行fork创建子进程,开销等同于bgsave过程。
(3.1)主进程fork操作完成后,继续响应其他命令。所有修改命令依然写入AOF缓冲区并根据appendfsync策略同步到硬盘,保证原有AOF机制正确性。
(3.2)由于fork操作运用写时复制技术,子进程只能共享fork操作时的内存数据。由于父进程依然响应命令,Redis使用“AOF重写缓冲区”保存这部分新数据,防止新AOF文件生成期间丢失这部分数据。
(4)子进程根据内存快照,按照命令合并规则写入到新的AOF文件。每次批量写入硬盘数据量由配置aof-rewrite-incremental-fsync控制,默认为32MB,防止单次刷盘数据过多造成硬盘阻塞。
(5.1)新AOF文件写入完成后,子进程发送信号给父进程,父进程更新统计信息,具体见info persistence下的aof_*相关统计。
(5.2)父进程把AOF重写缓冲区的数据写入到新的AOF文件。
(5.3)使用新AOF文件替换老文件,完成AOF重写。

2.5重启加载

AOF和RDB文件都可以用于服务器重启时的数据恢复。如图所示,表示Redis持久化文件加载流程。
在这里插入图片描述流程说明:
(1)AOF持久化开启且存在AOF文件时,优先加载AOF文件。
(2)AOF关闭或者AOF文件不存在时,加载RDB文件。
(3)加载AOF/RDB文件成功后,Redis启动成功。
(4)AOF/RDB文件存在错误时,Redis启动失败并打印错误信息。

2.6文件校验

加载损坏的AOF文件时会拒绝启动对于错误格式的AOF文件,先进行备份,然后采用redis-check-aof–fix命令进行修复,修复后使用diff-u对比数据的差异,找出丢失的数据,有些可以人工修改补全。AOF文件可能存在结尾不完整的情况,比如机器突然掉电导致AOF尾部文件命令写入不全。Redis为我们提供了aof-load-truncated配置来兼容这种情况,默认开启。加载AOF时,当遇到此问题时会忽略并继续启动,同时打印警告日志。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Netocc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值