Redis的持久化:RDB快照与AOF日记,数据安全的“底裤”如何选?

51 阅读7分钟

程序员最怕什么?不是需求变更,不是线上BUG,而是——服务器突然断电,Redis里缓存的海量数据…说没就没了! 那感觉,就像辛苦写了三天的代码,还没来得及 Ctrl + S

大家好,我是你们的老朋友,一名在后台疯狂CRUD的博主。今天我们不聊并发编程,也不扯微服务,来聊聊Redis的“底裤”问题——持久化

什么叫持久化?简单说,就是把内存中的数据写到磁盘上,防止系统宕机或重启后数据丢失。你可以把它理解为游戏存档,总不能每次重启游戏都从新手村开始吧?

Redis提供了两种经典的“存档”方式:RDBAOF。它们就像《火影忍者》里的鸣人和佐助,一个简单粗暴力量大,一个精细操作技巧强。接下来,就带大家深入浅出地盘一盘它们。


一、 RDB模式:瞬间的快照大师

1. 什么是RDB?

RDB(Redis DataBase)是Redis的快照式持久化。它会在指定的时间间隔内,将内存中的数据全集以二进制压缩的形式保存到一个.rdb文件中。

这个过程就像给你内存里的所有数据拍了一张全家福。这张照片非常紧凑,恢复起来也飞快。

2. RDB的执行时机:看心情?不,看配置!

RDB可不是随便就拍的,它执行快照的时机主要有三个:

  1. 自动触发:这是我们最常用的方式。在 redis.conf 配置文件中,我们可以用save指令设置规则。

    save 900 1      # 900秒(15分钟)内至少有1个key发生变化
    save 300 10     # 300秒(5分钟)内至少有10个key发生变化
    save 60 10000   # 60秒内至少有10000个key发生变化
    

    只要满足任意一条,Redis就会自动触发bgsave命令来创建RDB快照。是不是很像手机的自动备份?

  2. 手动触发:使用 savebgsave 命令。

    • save同步执行,阻塞所有客户端请求,直到快照完成。生产环境绝对禁用!(除非你想体验服务卡死的快感)
    • bgsave异步执行,Redis会fork()出一个子进程来负责创建RDB文件,主进程继续处理客户端请求。推荐使用!
  3. 被动触发:比如执行 flushall 清空数据库时,或者主从复制时全量同步,也会生成RDB文件。

3. RDB的执行原理:fork()大法好!

当你执行 bgsave 时,Redis会这样做:

  1. 主进程调用 fork() 系统调用,创建一个子进程。这个子进程和主进程拥有完全相同的内存数据。

    小知识:fork() 出来的子进程,在开始时并不会真正复制物理内存,而是与父进程共享同一内存页。只有当父进程或子进程尝试修改某块数据时,这块数据才会被复制一份(Copy-On-Write,写时复制)。这极大地节省了内存和创建进程的开销。

  2. 主进程继续快乐地处理客户端命令。

  3. 子进程则吭哧吭哧地将共享的内存数据遍历写入到一个临时的RDB文件中。

  4. 子进程写完(拍完照)后,用这个临时文件替换掉旧的RDB文件,然后功成身退。

整个过程,主进程只在fork()的那一刻有极其短暂的阻塞,后续全程无感,保证了高性能。

4. RDB的优缺点:力量大,但不够细

优点:

  • 性能高,恢复快:体积小,二进制压缩格式,重启时恢复大数据集速度非常快。
  • 适合灾难恢复:可以将某个时间点的完整数据备份到远程,非常适合做容灾。
  • 最大化Redis性能fork子进程进行持久化,对主进程影响极小。

缺点:

  • 数据安全性低:容易丢失最后一次快照之后的数据。比如你设置5分钟存一次,服务器在4分59秒宕机了,那这5分钟的数据就全没了。
  • fork()可能阻塞:虽然fork()本身很快,但如果数据集非常大,fork过程可能会阻塞主进程(虽然通常只是毫秒级)。

二、 AOF模式:兢兢业业的记账先生

如果RDB是粗犷的拍照师傅,那AOF就是事无巨细的记账先生

1. 什么是AOF?

AOF(Append Only File)会记录下每一个写操作命令(比如set, sadd, hmset),并以文本追加的形式写入一个日志文件的末尾。

当Redis重启时,它会“回放”这个日志文件中的所有命令,来重建原始数据集。

2. 如何开启AOF?

默认情况下AOF是关闭的。需要在 redis.conf 中开启:

appendonly yes         # 将 no 改为 yes
appendfilename "appendonly.aof" # AOF文件名

3. AOF的执行时机:三种写回策略

AOF记录日志后,何时真正把日志写到磁盘上?这决定了安全性和性能的权衡。

  1. appendfsync always同步写回。每个写命令都立即同步到磁盘。最安全,基本不丢数据,但性能最差。适合对数据可靠性要求极高的场景。
  2. appendfsync everysec每秒写回。每秒批量同步一次。性能和安全的折中方案,也是默认的推荐策略。最多丢失1秒的数据。
  3. appendfsync no由操作系统控制。写命令只写到操作系统缓存里,由操作系统决定何时刷到磁盘。性能最好,但最不安全,一旦宕机可能丢失大量数据。

4. AOF的“膨胀”与重写

AOF文件会无限增长吗?比如你执行了100次 incr count,AOF文件就会记录100条命令。但恢复时,我们只需要最后set count 100这一条命令就够了。

这就是AOF文件重写(Rewrite) 要解决的问题。它会创建一个新的AOF文件,这个文件包含重建当前数据集所需的最少命令集合

重写的原理: 和RDB的bgsave类似,也是fork一个子进程,遍历数据库,将每个key当前对应的最精简命令写入新AOF文件。完成后替换旧文件。

5. AOF自动重写

我们不需要手动触发重写。Redis提供了两个配置阈值,当AOF文件大小达到一定比例时自动触发:

auto-aof-rewrite-percentage 100 # 当前AOF文件比上次重写后文件大小增长100%(翻倍)时
auto-aof-rewrite-min-size 64mb  # 且AOF文件大小至少达到64MB

两者同时满足时,就会自动触发 bgrewriteaof


三、 终极对决:RDB vs AOF,我该选谁?

特性RDB (Snapshotting)AOF (Append-only File)
数据一致性时间点快照,可能丢失大量数据命令日志,通常最多丢失1秒数据
文件体积 (二进制压缩) (文本命令日志,可重写优化)
恢复速度非常快相对较慢 (需要回放所有命令)
对性能影响fork子进程时短暂阻塞,整体影响小always策略影响大,everysec和no影响较小
优先级低 (如果AOF开启,Redis启动优先用AOF恢复)

四、 实际应用的选择:小孩子才做选择,成年人…

1. 数据不能丢?同时开启 RDB 和 AOF (appendonly yes)。这是生产环境最稳妥的方案。

  • AOF保证数据安全性,作为主持久化方式。
  • RDB用于做冷备、快速恢复和历史归档。

2. 追求极致性能,可容忍分钟级数据丢失?(如缓存场景)可以只使用RDB

3. 追求高可用,钱够机器多? 直接上Redis哨兵集群,让持久化和高可用解耦。持久化在从节点做,主节点全力对外提供服务。


结语

Redis的这两条“底裤”,RDB和AOF,没有绝对的好坏,只有适合的场景。理解它们的原理和优缺点,就像熟练使用Ctrl + S和版本控制工具一样,是后端工程师保障数据安全的必备技能。

希望这篇“风趣”的讲解能让你对Redis持久化有更深刻的理解。下次重启服务器时,心里是不是更有底了?

大家有什么问题或趣事,欢迎在评论区分享!别忘了点赞收藏,你的支持是我持续输出的最大动力!