Redis 的落地策略
Redis 的落地策略其实就是持久化(Persistence),主要有以下2种策略:
- RDB: 定时快照方式(snapshot)
- AOF: 基于语句追加文件的方式
RDB
RDB 文件非常紧凑,它保存了 Redis 某个时间点上的数据集。RDB 恢复大数据集时速度要比 AOF 快。但是 RDB 不适合那些对时效性要求很高的业务,因为它只保存了快照,在进行恢复时会导致一些时间内的数据丢失。实际在进行备份时,Redis 主要依靠 rdbSave()
函数,然后有两个命令会调用这个函数 SAVE
和 BGSAVE
,前者会同步调用,阻塞主进程导致会有短暂的 Redis-server 停止工作,后者会 fork 出子进程异步处理。
在调用 SAVE
或者 BGSAVE
时,只有发布和订阅功能的命令可以正常执行,因为这个模块和服务器的其他模块是隔离的。
下面的命令表示: “60 秒内有至少有 1000 个键被改动”时进行RDB文件备份。
redis-server> SAVE 60 1000
RDB 文件的结构
开头的REDIS
表示这是一个 RDB 文件,然后紧跟着 redis 的版本号,SELECT-DB
和 KEY-VALUES-PAIRS
构成了对一个数据库中的所有数据记录,其中 KEY-VALUES-PAIRS
具体结构如下,后面两个就不用说了。
其中对于不同的类型,RDB文件中有不同的 layout,具体就不写出来了。
AOF
AOF 可以通过设置的 fsync 策略配置,如果未设置 fsync ,AOF 的默认策略为每秒钟 fsync 一次,在这种配置下, fsync 会在后台线程执行,所以主线程不会受到打扰。但是像 AOF 这种策略会导致追加的文件非常大,而且在恢复大数据时非常缓慢,因为要把所有会导致写数据库的命令都重新执行一遍。AOF文件中实际存储的是 Redis 协议下的命令记录,因此非常易读。
当然 Redis 考虑到了 AOF 文件过大的问题,因此引入了 BGREWRITEAOF
命令进行重建 AOF 文件,保证可以减少大量无用的重复写操作。重建命令并不会去分析已有的 AOF 文件,而是将当前数据库的快照保存。
在 AOF 文件重写时,Redis 的具体逻辑如下:
- Redis 首先 fork 出一个子进程,子进程将新 AOF 文件的内容写入到临时文件。
- 对于所有新执行的写入命令,父进程一边将它们累积到一个缓存中,一边将这些改动追加到现有 AOF 文件的末尾: 这样即使在重写的中途发生停机,现有的 AOF 文件也还是安全的。
- 当子进程完成重写工作时,它给父进程发送一个信号,父进程在接收到信号之后,将缓存中的所有数据追加到新 AOF 文件的末尾。
- 现在 Redis 原子地用新文件替换旧文件,之后所有命令都会直接追加到新 AOF 文件的末尾。
Redis 会维持一个默认的AOF重写策略,当当前的AOF文件比上次重写之后的文件大小增大了一倍时,就会自动在后台重写AOF。