Redis 对外提供数据访问服务时, 使用的是常驻内存的数据. 为了在 Redis Server 重启之后数据还可以得到恢复, Redis 具备将数据持久化到硬盘中的能力.
全量模式的持久化 (RDB)
Redis Server 在多有 db 中存储的 key-value 可以理解为 Redis 的一个状态. 当发生写操作时, Redis 就会从一个状态切换到另外一个状态. 基于全量的持久化就是在某个时刻, 将 Redis 的所有数据持久化到硬盘中, 形成一个快照. 当 Redis 重启时, 通过加载最近一个快照数据, 可以将 Redis 恢复至最近一次持久化状态上.
1, 写入流程
Redis 的全量写入包含 2 种方式: save 和 bgsave, 两者的处理逻辑如下:
save 可以由客户端显示触发的, 也可以在 redis shutdown 时触发. Save 本身是单线程串行化的方式执行的, 因此当数据量大时, 有肯能会发生 Redis Server 的长时间卡顿. 但是其备份期间不会有其他命令执行, 因此备份在这一时刻是一致性的.
bgsave 也可以由客户端显示触发, 可以通过配置定时任务触发也可以在 master-slave 的分布式结构下由 slave 节点触发. bgsave 命令在执行的时候, 会 fork 一个子进程. 子进程提交完成之后, 会立即给客户端返回响应, 备份操作在后台异步执行, 在此期间不会影响 Redis 的正常响应.
image
对于 bgsave 来说, 当父进程 Fork 完子进程之后, 异步任务会将当前的内存状态作为一个版本进行复制. 在复制过程中产生的变更, 不会反映在这次备份当中. 在 Redis 的默认配置当中, 当满足下面任一条件时, 会自动触发 bgsave 的执行.
<caption style="box-sizing: border-box; padding-top: 8px; padding-bottom: 8px; color: rgb(119, 119, 119); text-align: left;"> 自动触发 bgsave 条件 </caption>
配置 | seconds | changes |
---|---|---|
save | 900 | 1 |
save | 300 | 10 |
save | 60 | 10000 |
bgsave 相对于 Save 来说, 其优势是异步执行, 不影响后续的命令执行. 但是 Fork 子进程时, 涉及父进程的内存复制, 此时会增加服务器的内存开销. 当内存开销高到使用虚拟内存时, bgsave 的 Fork 子进程会阻塞运行, 可能会造成秒级的不可用. 因此使用 bgsave 需要保证服务器空闲内存足够.
<caption style="box-sizing: border-box; padding-top: 8px; padding-bottom: 8px; color: rgb(119, 119, 119); text-align: left;">save 和 bgsave 对比 </caption>
命令 | save | bgsave |
---|---|---|
IO 类型 | 同步 | 异步 |
是否阻塞 | 阻塞 | 非阻塞(在 fork 是阻塞) |
复杂度 | O(n) | O(n) |
优点 | 不会消耗额外内存 | 不阻塞客户端命令 |
缺点 | 阻塞客户端命令 | 需要 Fork 子进程,内存开销大 |
2, 恢复流程
当 Redis 重新启动时, 会从本地磁盘加载之前持久化的文件. 当恢复完成之后, 再受理后续的请求操作.
增量模式的持久化 (AOF)
RDB 记录的是每个状态的全量数据, 而 AOF(append-only-file) 记录的则是每条写命令的记录, 通过所有写命令的执行, 最后恢复出最终的数据状态. 其文件的生成如下所示:
image
1, 写入流程
Redis 的 AOF 包含 3 种同步策略:
always: 每一次的刷新缓冲区, 都会同步触发同步操作. 因为每次的写操作都会触发同步, 所以该策略会降低 Redis 的吞吐量, 但是这种模式会拥有最高的容错能力.
every second: 每秒异步的触发同步操作, 这种是 Redis 的默认配置.
no: 由操作系统决定何时同步, 这种方式 Redis 无法决定何时落地, 因此不可控.
image
<caption style="box-sizing: border-box; padding-top: 8px; padding-bottom: 8px; color: rgb(119, 119, 119); text-align: left;">always/everysec/no 对比 </caption>
命令 | always | everysec | no |
---|---|---|---|
优点 | 不丢失数据 | 每秒 1 次 fsync,丢 1 秒数据 | 无需设置 |
缺点 | IO 开销大,一般的 STAT 盘只有几百 TPS | 丢 1 秒数据 | 不可控 |
2, 回放流程
AOF 的回放时机也是在机器启动时, 一旦存在 AOF,Redis 会选择增量回放. 因为增量的持久化持续的写入磁盘, 相比全量持久化, 数据更加完整. 回放的过程就是将 AOF 中存放的命令, 重新执行一遍. 完成之后再继续接受客户端的新命令.
AOF 模式的优化重写
随着 Redis 持续的运行, 会有大量的增量数据 append 到 AOF 文件中. 为了减小硬盘存储和加快恢复速度, Redis 通过 rewrite 机制合并历史 AOF 记录. 如下所示:
image
整个流程描述如下:
历史 AOF: 以快照的方式保存.
快照写入期间的增量: 待快照写入完成之后 append 到快照文件中.
后续的增量: 写入新的 AOF.
来源: http://www.jianshu.com/p/5efef01a0e9f