数据持久化

深夜的故障

Redis 方案上线后,系统运行稳定,性能提升了 100 倍。

我以为可以高枕无忧了,直到有一天…

凌晨 3 点,手机响了。

【监控报警】Redis 服务器重启
时间:2023-08-15 03:12:45
原因:服务器内存溢出,自动重启
状态:服务已恢复

我打开电脑,查看 Redis 状态:

验证要点

  • 命令只用于验证系统状态,读者不需要记具体参数。

数据全部丢失了!

所有文章的点赞数都变成了 0,用户看不到自己的点赞记录。

这是一次严重的数据丢失事故。

为什么数据丢失?

我查阅了 Redis 的文档,找到了原因:

Redis 数据存储在内存中:
- 读写速度极快(纳秒级)
- 但内存是易失性存储
- 服务器重启后,内存数据丢失

默认配置:
- 没有开启持久化
- 重启后数据全部丢失

我忽略了数据持久化!

Redis 持久化方案

Redis 提供了两种持久化方案:

方案 1:RDB(快照)

原理:

  • 定期将内存中的数据保存到磁盘
  • 生成一个快照文件(dump.rdb)
  • 重启时加载快照恢复数据

配置方式:

验证要点

  • 命令只用于验证系统状态,读者不需要记具体参数。

手动触发快照:

验证要点

  • 命令只用于验证系统状态,读者不需要记具体参数。

优点:

  • 文件紧凑,适合备份
  • 恢复速度快(直接加载文件)
  • 对性能影响小(异步保存)

缺点:

  • 可能丢失最后一次快照后的数据
  • 快照生成期间,数据量大时会影响性能

数据丢失窗口:

配置:save 60 10000

时间线:
T0: 生成快照 dump.rdb
T1 ~ T60: 10000 次点赞操作
T60: 触发新的快照

如果在 T45 服务器宕机:
- 丢失 T1 ~ T45 的 7500 次点赞数据
- 只能恢复 T0 时刻的数据

方案 2:AOF(追加文件)

原理:

  • 记录所有写操作命令
  • 追加到文件末尾(appendonly.aof)
  • 重启时重新执行所有命令恢复数据

配置方式:

验证要点

  • 命令只用于验证系统状态,读者不需要记具体参数。

AOF 文件内容示例:

*3
$3
SET
$23
article:123:like_count
$4
1000
*3
$4
INCR
$23
article:123:like_count
*3
$4
SADD
$25
article:123:liked_users
$3
101

优点:

  • 数据更安全,最多丢失 1 秒数据
  • 文件可读,便于分析
  • 支持重写,压缩文件大小

缺点:

  • 文件体积大
  • 恢复速度慢(需要重放所有命令)
  • 对性能有影响(频繁写磁盘)

AOF 重写:

随着操作增多,AOF 文件越来越大:

原始操作:
INCR article:1:like_count  → 1
INCR article:1:like_count  → 2
INCR article:1:like_count  → 3
...
INCR article:1:like_count  → 100

重写后:
SET article:1:like_count 100

重写效果:
- 文件大小减少 90%
- 恢复速度提升

配置 AOF 重写:

验证要点

  • 命令只用于验证系统状态,读者不需要记具体参数。

方案 3:RDB + AOF(推荐)

原理:

  • 同时开启 RDB 和 AOF
  • AOF 保证数据安全
  • RDB 加快恢复速度

配置方式:

验证要点

  • 命令只用于验证系统状态,读者不需要记具体参数。

恢复流程:

Redis 重启:
1. 检查是否存在 AOF 文件
2. 如果存在,加载 AOF 文件恢复数据
3. 如果不存在,检查 RDB 文件
4. 如果存在,加载 RDB 文件恢复数据
5. 如果都不存在,启动空的 Redis

优缺点:

方案数据安全恢复速度性能影响推荐场景
RDB允许丢失几分钟数据
AOF不能丢失数据
RDB + AOF最高生产环境推荐

点赞场景的持久化策略

分析需求

点赞数据特点:
1. 写入频繁:每秒可能有数千次点赞
2. 重要性高:用户点赞数据不能丢失
3. 数据量大:数百万篇文章,每篇数千点赞

持久化需求:
- 尽量少丢失数据
- 恢复时间可接受
- 对性能影响最小

推荐配置

验证要点

  • 命令只用于验证系统状态,读者不需要记具体参数。

效果:

数据安全性:
- 最多丢失 1 秒数据(AOF)
- 即使 AOF 损坏,还能用 RDB 恢复大部分数据

恢复速度:
- 优先加载 AOF:数据完整
- 如果 AOF 损坏,加载 RDB:数据基本完整

性能影响:
- AOF 每秒同步:对性能影响约 10%
- RDB 定期快照:对性能影响约 5%
- 总体影响:约 15%(可接受)

数据丢失后的恢复

即使配置了持久化,仍可能发生数据丢失。我需要一个恢复方案。

方案:数据库同步 + 缓存重建

思路:

  • Redis 作为缓存,数据库作为数据源
  • 定期将 Redis 数据同步到数据库
  • Redis 数据丢失后,从数据库重建

实现:

定时任务配置:

实际效果

配置持久化后

Redis 配置:
- RDB:每分钟保存一次快照
- AOF:每秒同步一次

效果:
- 重启后数据自动恢复
- 最多丢失 1 秒数据
- 对性能影响约 15%

监控数据

验证要点

  • 命令只用于验证系统状态,读者不需要记具体参数。

性能对比

无持久化:
- 写入吞吐量:约 8000 ops/s
- 响应时间:0.1ms

RDB 持久化:
- 写入吞吐量:约 7500 ops/s(-6%)
- 响应时间:0.12ms

AOF 持久化(everysec):
- 写入吞吐量:约 7000 ops/s(-12%)
- 响应时间:0.15ms

RDB + AOF:
- 写入吞吐量:约 6500 ops/s(-19%)
- 响应时间:0.18ms

结论:性能损失可接受,数据安全性大幅提升

课后练习

练习 1

RDB 和 AOF 各有什么优缺点?如何选择?

参考答案(4 个标签)
Redis持久化RDBAOF

RDB vs AOF 对比

特性RDBAOF
原理定期快照追加写命令
文件大小小(压缩二进制)大(文本命令)
恢复速度
数据安全低(可能丢失分钟级数据)高(最多丢失 1 秒)
性能影响中等
可读性不可读可读

RDB 优缺点详解

优点:
1. 文件紧凑
   - 压缩后的二进制格式
   - 适合备份和传输
   - 文件大小通常是内存数据的 50%~80%

2. 恢复速度快
   - 直接加载到内存
   - 大数据集恢复时间秒级

3. 对性能影响小
   - 异步保存,不阻塞主线程
   - 可以设置保存间隔

缺点:
1. 数据安全性低
   - 只能保存最近一次快照的数据
   - 两次快照之间的数据可能丢失
   - 如果 Redis 崩溃,丢失最后一次快照后的所有数据

2. 快照生成时可能影响性能
   - 数据量大时,fork 子进程消耗内存
   - 写时复制(Copy-on-Write)可能占用额外内存

3. 不适合实时持久化
   - 频繁快照会影响性能
   - 不适合对数据完整性要求高的场景

AOF 优缺点详解

优点:
1. 数据安全性高
   - appendfsync always:每次写操作都同步,不丢失数据
   - appendfsync everysec:每秒同步,最多丢失 1 秒数据

2. 文件可读
   - 文本格式,可以直接查看
   - 便于分析和修复
   - 误操作时可以手动修改文件恢复

3. 支持重写
   - 自动压缩 AOF 文件
   - 减少文件体积
   - 加快恢复速度

缺点:
1. 文件体积大
   - 记录所有写命令
   - 文件大小远大于 RDB
   - 需要定期重写

2. 恢复速度慢
   - 需要重放所有命令
   - 大数据集恢复时间分钟级

3. 对性能影响较大
   - 每次写操作都要记录
   - 频繁磁盘 IO
   - appendfsync always 会严重影响性能

选择建议

场景 1:只用于缓存(数据可以丢失)
→ 只用 RDB,或不开启持久化

场景 2:数据不能丢失,但允许丢失少量
→ AOF + appendfsync everysec

场景 3:数据非常重要,不能丢失
→ RDB + AOF(双保险)

场景 4:数据量很大,恢复时间要短
→ RDB 为主,AOF 为辅

点赞场景选择

点赞数据:
- 数据重要,不能丢失
- 写入频繁
- 需要快速恢复

推荐:RDB + AOF
- AOF 保证数据安全
- RDB 加快恢复速度
- 定期同步到数据库作为最终备份

练习 2

如何配置 Redis 持久化,平衡性能和数据安全?

参考答案(3 个标签)
Redis配置持久化策略

生产环境推荐配置

验证要点

  • 命令只用于验证系统状态,读者不需要记具体参数。

不同业务场景的配置

验证要点

  • 命令只用于验证系统状态,读者不需要记具体参数。

性能优化技巧

验证要点

  • 命令只用于验证系统状态,读者不需要记具体参数。

监控和调优

验证要点

  • 命令只用于验证系统状态,读者不需要记具体参数。

练习 3

AOF 文件损坏后如何修复?

参考答案(3 个标签)
RedisAOF数据恢复

AOF 文件损坏场景

场景 1:写入过程中断电
- 最后一条命令可能不完整

场景 2:磁盘空间不足
- 文件可能被截断

场景 3:系统崩溃
- 文件可能损坏

修复方法 1:Redis 自带工具

验证要点

  • 命令只用于验证系统状态,读者不需要记具体参数。

修复方法 2:手动修复

验证要点

  • 命令只用于验证系统状态,读者不需要记具体参数。

修复方法 3:使用 RDB 恢复

验证要点

  • 命令只用于验证系统状态,读者不需要记具体参数。

修复方法 4:从数据库恢复

预防措施

验证要点

  • 命令只用于验证系统状态,读者不需要记具体参数。

完整修复流程

发现 AOF 文件损坏:
1. 停止 Redis 服务
2. 备份当前 AOF 文件
3. 尝试 redis-check-aof --fix
4. 如果修复失败,使用 RDB 恢复
5. 如果 RDB 也损坏,从数据库恢复
6. 重启 Redis 并验证数据
7. 分析原因,防止再次发生

练习 4

如何实现 Redis 数据的跨机房备份?

参考答案(3 个标签)
Redis备份容灾

跨机房备份方案

方案 1:主从复制

架构:
机房东:
  Redis Master(读写)

机房 B:
  Redis Slave(只读)

复制流程:
1. Master 写入数据
2. 异步复制到 Slave
3. 机房 B 有完整数据副本

配置主从复制

验证要点

  • 命令只用于验证系统状态,读者不需要记具体参数。

方案 2:Redis Sentinel(哨兵)

架构:
机房东:
  Redis Master
  Sentinel 1

机房 B:
  Redis Slave
  Sentinel 2

第三方机房:
  Sentinel 3

故障转移:
1. Sentinel 监控 Master
2. 发现 Master 故障
3. 选举新 Master
4. 通知客户端切换

Sentinel 配置

验证要点

  • 命令只用于验证系统状态,读者不需要记具体参数。

方案 3:Redis Cluster

架构:
机房东:
  Master 1, Master 2, Master 3

机房 B:
  Slave 1, Slave 2, Slave 3

数据分片:
- 每个节点负责一部分数据
- Slave 作为备份
- 支持 Master 故障自动切换

方案 4:定期快照备份

验证要点

  • 命令只用于验证系统状态,读者不需要记具体参数。

定时备份

验证要点

  • 命令只用于验证系统状态,读者不需要记具体参数。

跨机房恢复

容灾演练脚本

验证要点

  • 命令只用于验证系统状态,读者不需要记具体参数。

练习 5

如何监控 Redis 持久化状态,及时发现潜在问题?

参考答案(3 个标签)
Redis监控运维

Redis 持久化监控指标

验证要点

  • 命令只用于验证系统状态,读者不需要记具体参数。

监控脚本

Prometheus + Grafana 监控

配置要点

  • 配置表达的是环境差异和运行参数,不是业务规则本身。
  • 队列、缓存、存储和服务参数决定系统在高峰期的缓冲能力。

Grafana 告警规则

配置要点

  • 配置表达的是环境差异和运行参数,不是业务规则本身。
  • 队列、缓存、存储和服务参数决定系统在高峰期的缓冲能力。

监控仪表板指标

RDB 指标:
- 上次保存时间
- 保存后的修改次数
- 保存状态
- 保存耗时趋势

AOF 指标:
- AOF 开启状态
- 文件大小
- 重写状态
- 重写耗时趋势
- fsync 延迟次数

通用指标:
- 内存使用量
- 连接数
- 命令执行次数
- 键空间大小

思考题

  1. 如果 Redis 内存不够,但又需要持久化,如何优化?

  2. AOF 重写过程中,新的写操作如何处理?

  3. 如何实现”增量持久化”,只持久化变化的数据?

💡 提示:这些问题没有标准答案,建议结合实际情况深入思考。