线程模型+持久化
线程模型
Redis线程模型:
“关于 Redis 的线程模型,我是这样理解的:
首先,Redis 的核心命令执行是单线程的。它采用 Reactor 模式,基于 I/O 多路复用(如 epoll)来监听海量客户端连接。因为数据主要在内存中操作,且避免了多线程的上下文切换和锁竞争,所以单线程效率很高。
其次,Redis 6.0 引入了多线程 I/O。这是因为随着网络带宽增加,单线程处理网络读写成了瓶颈。现在的多线程主要用于并行处理网络数据的读写和协议解析,而命令的执行依然是单线程串行执行的,这样既提升了性能,又保证了命令的原子性。
此外,Redis 还有一些后台线程(BIO),用于处理像大 Key 删除、AOF 刷盘这样的耗时操作,防止这些操作阻塞主线程。”
追问准备:面试官可能会问:“既然单线程这么好,为什么不用多线程执行命令?”
回答:“主要是因为 Redis 的操作都是内存级的,CPU 通常不是瓶颈。如果改成多线程执行命令,为了保证数据一致性,需要引入复杂的锁机制,这会带来巨大的开销,而且会让代码变得非常复杂,得不偿失。目前的方案(单线程执行 + 多线程 I/O)是在性能和复杂度之间做的完美平衡。”
RDB快照
核心概念:
RDB 是在某一个时间点将 Redis 内存中的全部数据生成一个快照(Snapshot),并写入磁盘(默认为 dump.rdb文件)。
触发机制
- 手动触发:
SAVE:同步执行。会阻塞 Redis 主线程,直到 RDB 完成。生产环境严禁使用。BGSAVE(Background Save):异步执行。Redis 主进程会fork出一个子进程,由子进程负责生成 RDB 文件,主进程继续处理请求。这是 RDB 的主要工作方式。
- 自动触发:
- 在
redis.conf中配置save <seconds> <changes>。例如save 900 1表示 900 秒内如果有至少 1 次修改,就触发 BGSAVE。
- 在
工作原理(Copy-On-Write)
这是面试高频考点。
- 执行
BGSAVE时,Redis 调用fork()创建子进程。 - 父子进程共享同一块内存数据。
- 子进程开始将数据写入临时的 RDB 文件。
- 此时,如果主进程收到写请求(修改数据),操作系统会使用写时复制(Copy-On-Write, COW)技术。主进程会将被修改的内存页复制一份副本进行修改,而子进程看到的仍然是旧的数据快照。这就保证了 RDB 文件的一致性。
优缺点
优点:
- 恢复速度快:RDB 文件是二进制压缩文件,加载时直接读入内存,速度远快于 AOF 重放命令。
- 体积小:文件紧凑,适合做冷备份和灾难恢复。
- 对性能影响小:由子进程处理,主进程几乎不阻塞(除了 fork 瞬间)。
缺点:
数据丢失风险大:如果在两次快照之间宕机,这期间的数据会丢失

fork 开销:如果数据集很大,
fork操作可能会比较耗时,导致主进程短暂停止响应(Stop-The-World)
AOF日志追加
核心概念:
AOF 记录的是每一个写命令(类似于 MySQL 的 binlog),以 RESP 协议 的格式追加到文件末尾(appendonly.aof)。
工作流程
**命令追加 (Append)**:执行写命令时,将命令追加到
aof_buf缓冲区。**文件写入 (Write) & 同步 (Sync)**:根据不同的策略将缓冲区内容写入并同步到磁盘。
==文件重写 (Rewrite)==:随着时间推移,AOF 文件会变得很大(比如对一个 key 操作了 100 次,AOF 记录了 100 条命令,但其实只有最后一条有效)。Redis 会 fork 子进程,根据当前内存数据生成最小的写命令集合,替换旧的 AOF 文件。
重写期间,主线程将新写命令同时写入:
原有 AOF 文件(保证旧 AOF 完整)
AOF 重写缓冲区
子进程完成后,主线程将重写缓冲区增量追加入新 AOF 文件,然后用新文件原子替换旧文件。
刷盘策略 (fsync)
==AOF先写到缓冲区【缓存区是操作系统的概念,操作系统会决定把自己的缓冲区数据刷盘,所以为什么可以操作系统控制的原因】,再刷盘==
这是 AOF 的关键配置,决定了数据安全性和性能的权衡:
appendfsync always:每条命令都同步刷盘。最安全,但性能最差(硬盘 I/O 成为瓶颈)。appendfsync everysec:每秒刷盘一次(==默认推荐==)。最多丢失 1 秒的数据。兼顾性能和安全。appendfsync no:由操作系统控制。性能最好,但数据丢失风险不可控。
优缺点
- 优点:
- 数据安全:默认每秒同步,最多丢失 1 秒数据;使用
always则基本不丢数据。 - 可读性强:AOF 文件是文本格式(RESP),可以手动打开查看或修复(例如不小心执行了
FLUSHALL,只要没触发重写,可以去掉该命令重启恢复)。
- 数据安全:默认每秒同步,最多丢失 1 秒数据;使用
- 缺点:
- 文件体积大:即使经过重写,通常也比 RDB 大。
- 恢复速度慢:重启时需要重新执行所有命令,数据量大时启动非常慢
AOF混合持久化方式
这是 Redis 4.0 引入的重大改进,也是目前生产环境的首选方案。
核心概念:
==基本流程和AOF一样==
==但是==在 AOF 重写(Rewrite) 的时候,不再单纯将内存数据转换为 RESP 命令写入 AOF,而是先将内存数据以 RDB 格式写入 AOF 文件的开头,然后再将重写缓冲区的增量命令(RESP格式)追加到文件末尾
文件结构
新的 AOF 文件结构如下:
1 | [RDB 格式的全量数据] + [AOF 格式的增量数据] |
优势
- 启动速度快:恢复时,先加载 RDB 部分(快),再重放 AOF 部分的增量命令(少)。
- 数据安全性高:结合了 AOF 的实时性。
如何开启:
在 redis.conf中设置 aof-use-rdb-preamble yes(Redis 5.0 之后默认开启)。
问题
Redis 重启时加载文件的顺序是什么?
- 如果开启了 AOF,优先加载 AOF。
- 如果 AOF 关闭,或者 AOF 文件不存在,加载 RDB。
- 如果开启了混合持久化,AOF 文件其实是混合格式,Redis 会自动识别并先按 RDB 加载,再执行后续的 AOF 命令。
三种模式可以同时开启

数据丢失情况
- RDB可能会丢失两次快照之间的数据
- AOF按策略会丢失(例如每秒1次,则会丢失1秒的数据)
- 混合模式:混合模式的数据安全性与传统 AOF 是一样高的,不会因为用了混合模式就增加数据丢失的风险
如果丢失了怎么办?
如果不幸发生了数据丢失,我会分两步走:
第一是止损。如果是误操作,我会尝试利用 AOF 文件的日志特性,通过
redis-check-aof工具或手动编辑移除误操作命令来恢复;如果是宕机,我会利用现有的 RDB 或 AOF 文件重启恢复,并接受这部分时间窗口内的数据丢失。第二是复盘和预防。我会反思架构,强调单机的持久化机制(即使是混合模式)都存在理论上的数据丢失窗口。在生产环境中,必须通过部署主从架构来保证高可用,同时结合定期冷备 RDB 和 AOF 实时记录,构建多层防护体系,而不是仅仅依赖 Redis 自身的持久化。”
