vault backup: 2026-05-21 23:50:11
This commit is contained in:
+62
-1
@@ -107,6 +107,34 @@ flowchart TD
|
||||
E1 & E2 ==> "Footer"
|
||||
```
|
||||
|
||||
### 各段含义
|
||||
|
||||
| 段落 | 内容 | 说明 |
|
||||
|------|------|------|
|
||||
| **Header** | Magic + Version + 校验 | `REDIS` 魔数标识文件类型;版本号用于兼容性判断;CRC64 用于完整性校验 |
|
||||
| **DB Selector** | 数据库编号 | 默认 16 个 DB(0-15),只序列化非空 DB |
|
||||
| **Key-Value Pairs** | 类型 + 编码 + 数据 | 每个 key 携带类型标记(String/List/Hash/ZSet…),底层编码直接序列化,因此文件极紧凑 |
|
||||
| **EOF** | `0xFF` 终止符 | 标识数据段结束 |
|
||||
| **Footer** | CRC64 校验和 | 8 字节,启动加载时校验文件完整性 |
|
||||
|
||||
> [!QUESTION] 为什么 RDB 文件比 AOF 小很多?
|
||||
> 因为 RDB 直接序列化底层数据结构(如 ziplist、intset),而非记录产生这些数据的命令字符串。一个 Hash 用 ziplist 存储可能只有几十字节,但生成它的 HSET 命令可能有数百字节。
|
||||
|
||||
## 关键配置参数
|
||||
|
||||
```conf
|
||||
# ---- RDB 核心参数 ----
|
||||
dbfilename dump.rdb # 快照文件名
|
||||
dir /var/lib/redis # 工作目录,RDB/AOF 文件存放位置
|
||||
rdbcompression yes # 是否使用 LZF 压缩字符串(推荐开启,CPU vs 磁盘权衡)
|
||||
rdbchecksum yes # 是否在文件末尾写入 CRC64 校验(推荐开启)
|
||||
rdb-save-incremental-fsync yes # 写入磁盘时增量 fsync,避免一次性大量 I/O 阻塞
|
||||
rdb-del-sync-files no # 无盘复制时,是否删除用于同步的临时 RDB(Redis 7+)
|
||||
```
|
||||
|
||||
> [!TIP] rdbcompression 的取舍
|
||||
> 开启压缩可以显著减少磁盘占用(通常压缩 40%-60%),代价是写入时多消耗一点 CPU。对于绝大多数场景,**保持 yes** 是最优解。只有在 CPU 极度敏感、磁盘充裕的特殊场景下才考虑关闭。
|
||||
|
||||
## Fork 过程详解
|
||||
|
||||
```mermaid
|
||||
@@ -132,6 +160,26 @@ sequenceDiagram
|
||||
> [!WARNING] COW 内存消耗
|
||||
> fork 后主进程若持续写入大值,会导致 COW 副本膨胀。例如你有一个 1GB 的值被频繁修改,fork 后每次写都可能多拷贝一页(4KB)。高峰期建议关闭自动 RDB,仅依赖 AOF。
|
||||
|
||||
### 深入理解 COW(Copy-On-Write)
|
||||
|
||||
fork 后父子进程共享同一份物理内存页(只读),只有当某一方**写入**时,内核才会真正复制该页——这就是"写时复制"。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
F["Fork 完成"] --> S["父子进程共享<br/>所有物理内存页"]
|
||||
S --> W{"主进程收到<br/>写请求?"}
|
||||
W -->|"否"| R["子进程继续读取<br/>(零拷贝, 极快)"]
|
||||
W -->|"是"| C["内核复制该内存页<br/>(Copy-On-Write)"]
|
||||
C --> N["主进程写入副本<br/>子进程仍读原页"]
|
||||
R & N --> D["子进程完成序列化"]
|
||||
D --> DONE["RDB 文件生成"]
|
||||
```
|
||||
|
||||
> [!QUESTION] 为什么 Redis 占用内存会翻倍?
|
||||
> 这是面试高频题。答案是:**不会翻倍,但最坏情况接近翻倍。** fork 本身不复制内存,只有**主进程实际写入的页面**才会被 COW。如果 BGSAVE 期间主进程几乎不写入,额外内存开销几乎为零。但若全量写入,就会逐步逼近 2 倍。
|
||||
>
|
||||
> **运维经验**:保持系统 `vm.overcommit_memory=1`(Linux 默认),否则 fork 可能因内核认为内存不足而失败。
|
||||
|
||||
### TTL / 过期键处理
|
||||
|
||||
> [!QUESTION] RDB 快照会保存已过期的 key 吗?
|
||||
@@ -206,6 +254,19 @@ flowchart LR
|
||||
|
||||
> [!TIP] 混合持久化几乎是无脑开启的配置——启动快 + 不丢数据。
|
||||
|
||||
## 最佳实践
|
||||
|
||||
> [!SUMMARY] 核心原则:RDB 是备份手段,不是实时数据保障
|
||||
|
||||
1. **不要只依赖 RDB**:生产环境推荐 `AOF + RDB` 混合持久化,AOF 保证数据安全性,RDB 保证快速恢复
|
||||
2. **合理设置触发频率**:默认三档(900s/300s/60s)适合大部分场景;写入密集型业务可适当提高频率,但注意 fork 开销
|
||||
3. **监控 fork 耗时**:`INFO persistence` 中的 `rdb_last_bgsave_time_sec`,超过 1s 就需要关注
|
||||
4. **备份策略**:定期将 `.rdb` 文件拷贝到异地存储(S3/OSS),建议保留多个历史版本
|
||||
5. **磁盘选择**:RDB 文件写入对磁盘 I/O 有要求,建议使用 SSD 并配合 `rdb-save-incremental-fsync`
|
||||
|
||||
> [!WARNING] 大 Key 是 RDB 的天敌
|
||||
> 一个 100MB 的 String key,序列化时会导致子进程写入耗时剧增,同时 COW 也可能产生大量页面复制。发现大 Key 后应优先拆分。
|
||||
|
||||
## 运维要点
|
||||
|
||||
```bash
|
||||
@@ -225,4 +286,4 @@ tar czf redis-backup.tar.gz dump.rdb
|
||||
|
||||
- [[hhs/Redis/05-AOF持久化]] — AOF 持久化机制
|
||||
- [[hhs/Redis/06-主从与哨兵]] — Sentinel 故障转移流程
|
||||
- [[hhs/Redis/09-运维调优]] — 备份策略与大 Key 治理
|
||||
- [[hhs/Redis/11-运维与性能调优]] — 备份策略与大 Key 治理
|
||||
|
||||
Reference in New Issue
Block a user