Redis持久化的取舍和选择(RDB&AOF)
1 全量模式的持久化(RDB)
![](https://img.haomeiwen.com/i4685968/880b3c0ebb1788f9.png)
![](https://img.haomeiwen.com/i4685968/8e8ab486151a7871.png)
![](https://img.haomeiwen.com/i4685968/3bf175f513d864b6.png)
![](https://img.haomeiwen.com/i4685968/dab80439ea57c3b7.png)
![](https://img.haomeiwen.com/i4685968/88e87c14b5bed365.png)
![](https://img.haomeiwen.com/i4685968/93ee280a312cfa28.png)
![](https://img.haomeiwen.com/i4685968/8912f41e87ca8672.png)
![](https://img.haomeiwen.com/i4685968/64a1d8f68c723113.png)
![](https://img.haomeiwen.com/i4685968/0649dd6afd53d22f.png)
![](https://img.haomeiwen.com/i4685968/5986313dae5b37b6.png)
![](https://img.haomeiwen.com/i4685968/f20704e89de71d24.png)
![](https://img.haomeiwen.com/i4685968/f1c4ab42e57155a0.png)
![](https://img.haomeiwen.com/i4685968/37262750d8da3809.png)
![](https://img.haomeiwen.com/i4685968/231f292d7e6d658f.png)
![](https://img.haomeiwen.com/i4685968/8cb12019c9cf832d.png)
![](https://img.haomeiwen.com/i4685968/1f07f54b0aab6278.png)
![](https://img.haomeiwen.com/i4685968/ea172ae1f0d6add3.png)
![](https://img.haomeiwen.com/i4685968/614a3eeab165e3aa.png)
![](https://img.haomeiwen.com/i4685968/0e759c4faccf3bf4.png)
导入大量数据
![](https://img.haomeiwen.com/i4685968/aad7d6ac95e66405.png)
![](https://img.haomeiwen.com/i4685968/f11c46806fa41929.png)
save 命令是阻塞式执行的!!!!!, save时无法进行其他命令操作!!!
接着验证 bgsave
![](https://img.haomeiwen.com/i4685968/3af3d9f25b956333.png)
非阻塞式命令!!!
![](https://img.haomeiwen.com/i4685968/75adf958ed217f89.png)
![](https://img.haomeiwen.com/i4685968/ae45f55b9d7c28de.png)
![](https://img.haomeiwen.com/i4685968/56f64f179349e803.png)
Redis 对外提供数据访问服务时,使用的是常驻内存的数据。为了在Redis Server重启之后数据还可以得到恢复,Redis具备将数据持久化到硬盘中的能力。
Redis Server在多有db 中存储的key-value可以理解为Redis的一个状态。当发生写操作时,Redis就会从一个状态切换到另外一个状态。基于全量的持久化就是在某个时刻,将Redis的所有数据持久化到硬盘中,形成一个快照。当Redis 重启时,通过加载最近一个快照数据,可以将Redis 恢复至最近一次持久化状态上。
![](https://img.haomeiwen.com/i4685968/b2a042d37b15f8d9.png)
1、写入流程
Redis的全量写入包含2种方式:save 和 bgsave,两者的处理逻辑如下:
save 可以由客户端显示触发的,也可以在redis shutdown 时触发。Save本身是单线程串行化的方式执行的,因此当数据量大时,有肯能会发生Redis Server的长时间卡顿。但是其备份期间不会有其他命令执行,因此备份在这一时刻是一致性的。
bgsave 也可以由客户端显示触发、可以通过配置定时任务触发也可以在master-slave的分布式结构下由slave节点触发。bgsave命令在执行的时候,会fork一个子进程。子进程提交完成之后,会立即给客户端返回响应,备份操作在后台异步执行,在此期间不会影响Redis的正常响应。
![](https://img.haomeiwen.com/i4685968/bf0e0937538ccdbd.png)
对于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重新启动时,会从本地磁盘加载之前持久化的文件。当恢复完成之后,再受理后续的请求操作。
2 增量模式的持久化(AOF)
![](https://img.haomeiwen.com/i4685968/2e9a4661b10411bb.png)
![](https://img.haomeiwen.com/i4685968/db9f253c1dbd7972.png)
![](https://img.haomeiwen.com/i4685968/3d8483fcb243c977.png)
![](https://img.haomeiwen.com/i4685968/1b21d24f96187c4b.png)
![](https://img.haomeiwen.com/i4685968/6d6d2c485151315f.png)
![](https://img.haomeiwen.com/i4685968/7eecd9cf7e5fff17.png)
![](https://img.haomeiwen.com/i4685968/c007390c9cb54329.png)
![](https://img.haomeiwen.com/i4685968/7c5c3a5667d54393.png)
![](https://img.haomeiwen.com/i4685968/58607327abddc5d0.png)
![](https://img.haomeiwen.com/i4685968/a4d89ca8742ff714.png)
![](https://img.haomeiwen.com/i4685968/bbf3ddb9be41c5db.png)
![](https://img.haomeiwen.com/i4685968/4a87446cad26bb2a.png)
![](https://img.haomeiwen.com/i4685968/6a4dd0b269cc950e.png)
![](https://img.haomeiwen.com/i4685968/82daa76dee02aac3.png)
![](https://img.haomeiwen.com/i4685968/c8936ea9d3235510.png)
![](https://img.haomeiwen.com/i4685968/5f8beab511cef6b4.png)
![](https://img.haomeiwen.com/i4685968/37a476812f30e3e3.png)
![](https://img.haomeiwen.com/i4685968/b26aa52b86b210a1.png)
![](https://img.haomeiwen.com/i4685968/53b688673dab37cc.png)
![](https://img.haomeiwen.com/i4685968/356789cb067ad95a.png)
![](https://img.haomeiwen.com/i4685968/8160b987ac03fc01.png)
![](https://img.haomeiwen.com/i4685968/6cb8a42b3b4a0b14.png)
![](https://img.haomeiwen.com/i4685968/3769bb8acff2f54b.png)
![](https://img.haomeiwen.com/i4685968/f754ac81433f585e.png)
RDB记录的是每个状态的全量数据,而AOF(append-only-file)记录的则是每条写命令的记录,通过所有写命令的执行,最后恢复出最终的数据状态。其文件的生成如下所示:
![](https://img.haomeiwen.com/i4685968/693fc93b6a494658.png)
1、写入流程
Redis的AOF 包含3 种同步策略:
always:每一次的刷新缓冲区,都会同步触发同步操作。因为每次的写操作都会触发同步,所以该策略会降低Redis的吞吐量,但是这种模式会拥有最高的容错能力。
every second:每秒异步的触发同步操作,这种是Redis的默认配置。
no:由操作系统决定何时同步,这种方式Redis无法决定何时落地,因此不可控。
![](https://img.haomeiwen.com/i4685968/a2d9bd5f36e4562b.png)
<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 记录。如下所示:
![](https://img.haomeiwen.com/i4685968/583c4a2cfc4a3db7.png)
整个流程描述如下:
历史AOF:以快照的方式保存。
快照写入期间的增量:待快照写入完成之后append 到快照文件中。
后续的增量:写入新的AOF。
3 最终抉择及最佳实践
![](https://img.haomeiwen.com/i4685968/eaecfd3035d5ebde.png)
![](https://img.haomeiwen.com/i4685968/a494c9c5c917686f.png)
![](https://img.haomeiwen.com/i4685968/3b9c17df8e752cc2.png)
![](https://img.haomeiwen.com/i4685968/bdccaa3509b74063.png)