Redis 持久化的一些事
个人学习 Redis 的总结学习笔记,参考资料都在文末给出,建议阅读
内容较多,点赞收藏不迷路~
数据库状态:服务器中的非空数据库以及它们的键值对统称为数据库状态。
Redis 是内存型数据库,为了保证数据在断电后不会丢失,需要将内存中的数据持久化到硬盘上。
RDB
将某个时间点的所有数据都存放到硬盘上,以防数据意外丢失。
可以将快照复制到其它服务器从而创建具有相同数据的服务器副本。
如果系统发生故障,将会丢失最后一次创建快照之后的数据。
如果数据量很大,保存快照的时间会很长。
创建与写入
SAVE 命令会阻塞服务器直至 RDB 文件创建完成,期间服务器不能处理任何命令请求。
BGSAVE 派生一个子进程负责创建 RDB 文件,服务器不会被阻塞。
BGSAVE 和 SAVE 以及 BGSAVE 命令互斥,这是因为防止产生竞争条件。
RDB 文件在服务器启动时自动被载入,期间服务器处于阻塞状态,直至载入完成。
自动间隔保存
1. 执行命令
用户通过配置 save 选项可以控制服务器执行 BGSAVE 的时间间隔,save 的值会被在一个选项数组中保存下来。
save 选项默认设置:
操作 | 时间(秒) | 操作次数 |
---|---|---|
save | 900 | 1 |
save | 300 | 10 |
save | 60 | 10000 |
如,900秒内对数据库进行1次修改,就会执行 save 命令。
2. 记录状态
dirty 是一个计数器。
记录上一次服务器执行完保存命令到现在,服务器对数据库状态进行的修改次数。
服务器每执行成功修改,dirty 计数就会增加,增加数值为此次对数据库执行的修改次数。
lastsave 是 UNIX 时间戳,记录上一次执行保存命令的时间。
3. 检查保存条件
服务器的一个周期函数会检查 save 选项的所设置的条件是否已满足,至少有一个条件被满足,则服务器就会执行 BGSAVE 命令。
AOF
将写命令添加到 AOF 文件(Append Only File)的末尾。
服务器启动时自动加载和执行 AOF 文件来还原服务器被关闭之前的数据库状态。
1. 命令追加
服务器执行完一个命令后,会将被执行的写命令追加到服务器状态的 aof_buf 缓冲区的末尾。
2. 写入、同步
使用 AOF 持久化需要设置同步选项,从而确保写命令同步到磁盘文件上的时机。
这是因为对文件进行写入并不会马上将内容同步到磁盘上,而是先存储到缓冲区,然后由操作系统决定什么时候同步到磁盘。
根据选项设置,服务器会先将缓冲区内容写入到 AOF 文件中,然后再对 AOF 文件进行同步。
有以下同步选项:
选项 | 同步频率 |
---|---|
always | 每个写命令都写入并同步 |
everysec | 所有命令都会写入,然后每秒同步一次 |
no | 每个命令都会被写入,让操作系统来决定何时同步 |
- always 选项会严重减低服务器的性能;
- everysec 默认值,比较合适,可以保证系统崩溃时只会丢失一秒左右的数据,并且 Redis 每秒执行一次同步对服务器性能几乎没有任何影响;
- no 选项并不能给服务器性能带来多大的提升,而且也会增加系统崩溃时数据丢失的数量。
3. 重写
随着服务器写请求的增多,AOF 文件会越来越大。Redis 提供了一种将 AOF 重写的特性,能够去除 AOF 文件中的冗余写命令。
从服务器读取键现在的值,然后用一条命令去记录键值对,代替之前记录这个键值对的多条命令。
新 AOF 文件只包含还原当前状态所必须的命令,所以不会造成空间浪费。
使用后台子进程的方式处理重写功能,可以避免使用锁,以及保证数据安全。
Redis 设置 AOF 重写缓冲区来保证 重写后的 AOF 文件与当前数据库状态保持一致。
当新的 AOF 文件重写结束,会对它进行改名,并且保证原子性的情况下,直接覆盖旧的 AOF 文件。
对比
AOF 文件的更新频率通常比 RDB 文件的更新频率高。
-
RBD 保存的是数据快照, AOF 保存的是执行命令。
-
服务器优先使用 AOF 文件来还原数据库状态。
-
只有 AOF 处于关闭状态下,服务器才使用 RDB 文件来还原数据库状态。
-
如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。即使每5分钟都持久化一次,当redis故障时,仍然会有近5分钟的数据丢失。
-
在同样数据规模的情况下,AOF文件要比RDB文件的体积大。而且,AOF方式的恢复速度也要慢于RDB方式。
-
RDB需要定时持久化,风险是可能会丢两次持久之间的数据,量可能很大。
-
AOF每秒fsync一次指令硬盘,如果硬盘IO慢,会阻塞父进程;风险是会丢失1秒多的数据;在Rewrite过程中,主进程把指令存到mem-buffer中,最后写盘时会阻塞主进程。
拓展阅读
如果对你有帮助,请点个赞,加个收藏噢!
参考资料
《Redis设计与实践》
cyc2018