AOF (Append Only File)
在每个 “写” 命令被 redis 执行后,将该命令记录到 AOF 日志中。
为什么是在 “写” 命令执行后记录?
因为记录 AOF 时不会检查命令是否正确,而在命令执行后记录,可确保命令能被正确执行且不会阻塞主线程的 “写” 操作。
何时落盘?
- 主线程 fork 出一个后台子线程
bgrewriteaof
- 主线程会将子线程需要的数据结构拷贝一份,其中包括内存页表(虚拟内存和物理内存的映射索引表)
- 当前操作会阻塞主线程
- 子线程使用最新数据生成 “写” 命令并写入新的 AOF日志中
- 重写过程中,主线程写入新的数据时,在命令执行后将命令同时写入主线程的 AOF 日志以及子线程的 AOF 重写日志中
- 重写过程中,主线程修改旧数据时使用 “写时拷贝” 机制,即将需要修改的数据拷贝一个备份出来,主线程将新数据写入备份不会影响 AOF 的重写
- 步骤 2 执行完毕后,子线程会将 AOF 重写日志中的内容追加到新的 AOF 日志中
- 将子线程重写后的 AOF 日志替换主线程的 AOF 日志
RDB (Redis DataBase)
save
bgsave
会创建一个专门用于写入 RDB 的子线程
- fork 子线程时,会阻塞主线程
- 使用 “写时拷贝” 机制,避免数据不一致
- Redis 的默认方式
增量快照
所谓 “增量快照” 是指第一次快照全库数据,从第二次开始每次只快照那些在第一次快照后新增、修改的数据。RDB + AOF
Redis version >= 4.0
以一定频率执行快照,使用 AOF 记录每次快照间的操作,并在每次快照后清空 AOF 日志。
主从间如何保证数据的一致性?
前提:
- run_id:Redis 实例的唯一 id
- offset:偏移量
- 主库会持有一个环境列表,使用 offset 标识当前最新数据的位置
新增从库时
- 从库向主库发起请求、协商同步(run_id=? & offset=-1)
- 主库使用
FULLRESYNC
相应请求并返回 run_id & offset - 主库返回当前最新数据的全量 RDB 文件
- 从库清空现有数据后,加载 RDB
- 主库返回生成 RDB 期间所执行的 “写命令”
- 主从保持长链接
从库宕机恢复
- 从库连接恢复后,从库发送同步请求(run_id & offset)
- 主库发送 >从库 offset 且 <主库 offset 的增量数据
- 主从保持长链接