Redis持久化机制详解 | JavaGuide
Redis 不同于 Memcached 的很重要一点就是,Redis 支持持久化,而且支持 3 种持久化方式:
- 快照(snapshotting,RDB)
- 只追加文件(append-only file, AOF)
- RDB 和 AOF 的混合持久化(Redis 4.0 新增)
BRD持久化
快照持久化是 Redis 默认采用的持久化方式,在 redis.conf
配置文件中默认有此下配置:
save 900 1 #在900秒(15分钟)之后,如果至少有1个key发生变化,Redis就会自动触发bgsave命令创建快照。
save 300 10 #在300秒(5分钟)之后,如果至少有10个key发生变化,Redis就会自动触发bgsave命令创建快照。
save 60 10000 #在60秒(1分钟)之后,如果至少有10000个key发生变化,Redis就会自动触发bgsave命令创建快照。
RDB 创建快照时会阻塞主线程吗?
Redis 提供了两个命令来生成 RDB 快照文件:
save
: 同步保存操作,会阻塞 Redis 主线程;bgsave
: fork 出一个子进程,子进程执行,不会阻塞 Redis 主线程,默认选项。
这里说 Redis 主线程而不是主进程的主要是因为 Redis 启动之后主要是通过单线程的方式完成主要的工作。如果你想将其描述为 Redis 主进程,也没毛病。
AOF持久化
aof的实时性更好, 开启 AOF 持久化后每执行一条会更改 Redis 中的数据的命令,Redis 就会将该命令写入到 AOF 缓冲区 server.aof_buf
中,然后再写入到 AOF 文件中(此时还在系统内核缓存区未同步到磁盘),最后再根据持久化方式( fsync
策略)的配置来决定何时将系统内核缓存区的数据同步到硬盘中的。
只有同步到磁盘中才算持久化保存了,否则依然存在数据丢失的风险,比如说:系统内核缓存区的数据还未同步,磁盘机器就宕机了,那这部分数据就算丢失了。
AOF 文件的保存位置和 RDB 文件的位置相同,都是通过 dir
参数设置的,默认的文件名是 appendonly.aof
。
AOF的工作流程:
write
:写入系统内核缓冲区之后直接返回(仅仅是写到缓冲区),不会立即同步到硬盘。虽然提高了效率,但也带来了数据丢失的风险。同步硬盘操作通常依赖于系统调度机制,Linux 内核通常为 30s 同步一次,具体值取决于写出的数据量和 I/O 缓冲区的状态。fsync
:fsync
用于强制刷新系统内核缓冲区(同步到到磁盘),确保写磁盘操作结束才会返回。
AOF的三种同步策略:
- 如果是
appendfsync always
: 每个命令后立即写入 - 如果是
appendfsync everysec
: 每秒写入一次 - 如果是
appendfsync no
: 由操作系统决定何时写入
AOF 为什么是在执行完命令之后记录日志?
- 避免额外的检查开销,AOF 记录日志不会对命令进行语法检查;
- 在命令执行完之后再记录,不会阻塞当前的命令执行。
这样也带来了风险(我在前面介绍 AOF 持久化的时候也提到过):
- 如果刚执行完命令 Redis 就宕机会导致对应的修改丢失;
- 可能会阻塞后续其他命令的执行(AOF 记录日志是在 Redis 主线程中进行的)。
AOF 重写了解吗?
AOF重写流程: 流程图
- 触发重写:
- Redis可以根据配置自动触发重写(例如,当AOF文件大小超过上一次重写后的一定百分比)
- 或者通过手动执行BGREWRITEAOF命令触发
- 创建子进程:
- Redis主进程创建一个子进程来执行重写操作
- 这允许主进程继续服务客户端请求
- 创建数据快照:
- 子进程创建当前数据集的内存快照
- 重写AOF文件:
- 子进程遍历数据快照,生成重建当前数据集所需的最小命令集
- 这些命令被写入一个新的AOF文件
- 累积新写入:
- 在重写过程中,主进程继续处理写命令
- 这些新命令被写入旧的AOF文件,同时被存储在一个重写缓冲区中
- 同步新写入:
- 当子进程完成重写后,它通知主进程
- 主进程将重写缓冲区中的内容追加到新AOF文件末尾
- 切换文件:
- Redis执行一个原子性的替换操作,用新的AOF文件替换旧文件
- 完成重写:
- 重写过程完成,Redis继续使用新的AOF文件进行持久化
AOF重写的好处:
- 减小文件大小: 通过合并冗余命令,大幅减少AOF文件的大小
- 提高恢复速度: 更小的文件意味着更快的数据恢复
- 优化内存使用: 较小的AOF文件减少了磁盘和内存的使用
注意事项:
- 重写过程可能会暂时增加内存使用
- 在高负载情况下,可能会影响Redis的性能
AOF 校验机制了解吗?
主要是通过校验和的数字来验证 AOF 文件
- 校验和计算:
-
- Redis在每次AOF重写操作完成后,会对新的AOF文件内容进行CRC64算法计算,得出一个校验和。
- 校验和存储:
-
- 计算得到的校验和会被存储在一个单独的文件中,通常命名为[aof-file-name].manifest。
- 启动时检查:
-
- 当Redis启动时,它会读取AOF文件及其对应的manifest文件。
- Redis会重新计算AOF文件的CRC64校验和,并与manifest文件中存储的校验和进行比较。
- 完整性验证:
-
- 如果计算得到的校验和与存储的校验和匹配,Redis认为AOF文件是完整的。
- 如果校验和不匹配,Redis会报告AOF文件可能已损坏,并可能拒绝启动(取决于配置)。
RDB 和 AOF 的混合持久化
混合持久化的优点:
- 混合持久化结合了RDB的快速加载和AOF的数据安全性。
- 在AOF重写时,会同时使用RDB和AOF两种格式。
混合持久化的工作流程: 流程图
a. 触发AOF重写时,Redis执行以下步骤:
- 创建一个当前数据集的RDB快照。
- 将这个RDB快照写入新的AOF文件的开头。
- 从快照创建开始,之后的写操作以AOF格式追加到文件末尾。
b. 最终的AOF文件结构: [RDB数据][AOF增量数据]
优势:
- 快速加载:重启时可以快速加载RDB部分。
- 数据安全:最近的变更记录在AOF部分,提供了更好的数据安全性。
- 文件大小:通常比单纯的AOF文件小,因为RDB格式更紧凑。
重启过程:
- Redis重启时,先加载RDB部分恢复大部分数据。
- 然后执行AOF部分的命令来恢复最新的数据变更。
配置方式:
- 通过设置
aof-use-rdb-preamble yes
来启用混合持久化。 - 这个选项在Redis 4.0及以上版本可用。
注意事项:
- 混合持久化文件不向后兼容,旧版Redis可能无法解析。
- 在进行AOF重写时可能会暂时增加内存使用。
应用场景:
- 适合既需要快速恢复又要求高数据安全性的场景。
- 对于大型数据集特别有效,可以显著减少恢复时间。