在单机版 Redis 中,数据全部存放在内存里,一旦服务器停电或宕机,内存里的数据就会瞬间灰飞烟灭。为了保证数据的高可用和持久化,Redis 提供了两种主流方案,我们要学的第一个就“快照派”的代表:RDB。
📚 高级篇 02. Redis 持久化 - RDB 原理与演示文档
一、 核心认知:什么是 RDB?
RDB (Redis Database Backup file) ,也被叫做 Redis 数据快照。
你可以把它想象成给当前时刻的 Redis 内存状态**“拍了一张照片”**。它会把内存中的所有数据,经过极度压缩后,生成一个体积非常小的二进制文件(默认叫 dump.rdb),然后保存在硬盘上。
当 Redis 意外宕机重启时,它会自动读取硬盘上的 dump.rdb 文件,把“照片”里的数据重新加载到内存中,瞬间恢复生机。
二、 RDB 的触发机制与演示
要让 Redis 拍这张“照片”,有手动和自动两种方式。
1. 手动触发 (两条命令的生死对决)
在 Redis 客户端中,你可以直接输入命令来生成 RDB 文件。这里有两个极其相似但命运截然不同的命令:
-
❌
save命令 (绝对禁忌):- 执行逻辑: 由 Redis 的主进程亲自去执行快照保存。
- 致命后果: Redis 是单线程处理命令的。如果你的内存里有几十 GB 的数据,保存可能需要好几秒。在这几秒内,Redis 会被完全阻塞,拒绝所有前端用户的读写请求!如果在生产环境执行
save,基本等于主动制造一次“宕机”。
-
✅
bgsave命令 (企业标准):- 执行逻辑: Background Save。Redis 会在后台异步执行快照保存。
- 核心优势: 它会开启一个独立的子进程去写磁盘,主进程依然可以不受干扰地处理前端用户的增删改查请求。 (面试重点,底层原理见后文)
2. 自动触发 (修改 redis.conf 配置)
在真实的生产环境中,我们不可能靠人工盯着屏幕敲 bgsave。Redis 允许我们在配置文件 redis.conf 中设置自动触发条件。
打开 redis.conf,找到 SNAPSHOTTING 模块,你会看到类似这样的配置:
Properties
# 格式:save <指定时间间隔/秒> <执行指定次数更新操作>
save 3600 1 # 3600秒 (1小时) 内,至少有 1 个 key 被修改,就执行 bgsave
save 300 100 # 300秒 (5分钟) 内,至少有 100 个 key 被修改,就执行 bgsave
save 60 10000 # 60秒 (1分钟) 内,至少有 10000 个 key 被修改,就执行 bgsave
# 如果你想彻底禁用 RDB,可以写成:
# save ""
# RDB 文件的保存名称
dbfilename dump.rdb
# RDB 文件保存的目录 (通常配成你的持久化数据盘路径)
dir ./
三、 面试终极杀招:bgsave 的底层原理 (Copy-On-Write)
这是高级开发工程师面试中必问的 RDB 核心考点。
🤔 面试官发难: “你刚才说 bgsave 不会阻塞主进程,因为开启了子进程。但是,如果在子进程写磁盘的这几秒钟里,主进程同时接收到了修改数据的请求,子进程正在拍的照片会被弄花吗? ”
你的满分破局回答:
“不会弄花,因为 Redis 底层利用了操作系统的 fork() 机制和 Copy-On-Write (写时复制) 技术。
- Fork 瞬间: 当执行
bgsave时,主进程会调用fork()创建一个子进程。注意,子进程并没有拷贝主进程的物理内存数据,而是拷贝了主进程的虚拟内存页表。这意味着主进程和子进程此时共享着同一块物理内存。所以fork()的速度极快。- 写时复制 (COW) 发力: 子进程开始开心地把共享内存里的数据写到
dump.rdb文件里。此时,如果主进程只接到了用户的读请求,大家相安无事。- 拦截修改: 如果主进程接到了用户的写请求(比如要把 key 从 A 改成 B),操作系统会进行干预!它会先把要修改的这块内存页拷贝一份副本(Copy) 。
- 各干各的: 主进程在刚刚拷贝出来的副本上完成数据的修改(把 A 改成了 B)。而子进程依然在读取原来那块原始内存中的老数据(A)写入 RDB 文件。
这样,既保证了主进程能实时处理新请求,又保证了子进程拍出的一定是执行
bgsave那个精确时刻的完美快照,互不干扰!”
四、 RDB 的优缺点总结
了解了底层原理,RDB 的优缺点就非常清晰了:
👍 优点:
- 恢复速度极快:
dump.rdb是极其紧凑的二进制压缩文件,重启 Redis 时,直接把文件按字节塞进内存就行,恢复速度远超其他方案。 - 适合灾备: 体积小,非常适合每隔几小时备份一次,传到远程服务器上做容灾备份。
👎 缺点:
- 数据丢失风险大 (最大痛点): RDB 是定时执行的(比如 5 分钟一次)。如果系统在 4 分 59 秒时突然断电宕机,那么这 5 分钟内新写入的所有数据就永久丢失了!
- Fork 阻塞成本: 虽然子进程写磁盘不阻塞,但
fork()拷贝页表的那个瞬间,主进程是阻塞的。如果 Redis 内存极其巨大(比如 64GB),页表也会很大,fork()可能会导致几百毫秒的卡顿。
正因为 RDB 有着“两次快照之间的数据容易丢失”这个致命缺陷,对于对数据安全性要求极高(如金融、交易订单)的业务来说,是不可接受的。
为了解决这个问题,Redis 推出了它的另一大法宝,也是我们下一节要攻克的对象。