Redis(Remote Dictionary Server)是一个高性能的键值存储系统,它可以将数据存储在内存中以实现快速访问。为了保持数据的持久性,Redis 提供了两种数据持久化方法:RDB 和 AOF。
RDB(Redis Database)
RDB 是 一个 快照,是 Redis 的一个 定时 的持久化方法,通过将某个时间点上的内存数据集(会将内存中的键值对遍历一遍)生成一个二进制文件进行存储。RDB 文件通常具有较小的尺寸,因为它们是经过压缩的二进制文件。压缩会消耗CPU资源,可关闭。
1. RDB SAVE 为什么是同步的?
RDB 是同步进行的,主要是由于 RDB 持久化方式所采用的快照机制导致的。快照机制会将 Redis 的内存状态作为一个整体写入到磁盘上的 RDB 文件中,因此,在进行 RDB 持久化时,需要阻塞 Redis 服务器进程的所有线程,避免在保存过程中修改了数据而导致 RDB 文件出现错误。
2. RDB BGSAVE 为什么是异步的?
fork主进程得到一个子进程,共享内存空间。
子进程读取内存数据并写入新的RDB文件
主进程在 BGSAVE 期间接收到的修改指令会采用
copy-on-write
技术,不修改和子进程共享的内存空间,而是将修改的数据拷贝一个副本出来。
RDB 的优点:
- 适用于大规模数据恢复:由于 RDB 文件较小,所以在需要进行数据恢复时,可以较快地加载数据。
- 低延迟:RDB 持久化操作是在另一个子进程中进行的,对主进程的影响较小,可以保持高性能。
RDB 的缺点:
- 数据丢失:因为 RDB 是定期生成快照,所以在两次快照之间发生故障时,可能会丢失一部分数据。
- 快照生成可能会导致磁盘 I/O 和 CPU 使用率的短暂峰值,对于某些高负载的应用场景可能不适用。
AOF(Append Only File)
AOF 是 Redis 的一种 追加的 非阻塞式 的持久化方法,通过将每个写入命令追加到文件的方式,记录数据变更。在 Redis 启动时,可以通过重新执行 AOF 文件中的命令来恢复数据。
AOF 为什么是异步的?
AOF 在追加前,会先将数据缓存到缓冲区(aof_buf),默认的 fsync 策略是每秒将缓冲区内的数据追加到AOF文件中。
AOF 在重写(rewrite)是一个消耗性能与时间的过程,故设计成异步的,fork 一个子进程进行对 AOF 文件的重写。因为是异步,所以也会有新的请求发送给主进程,在重写的过程中主进程处理的改写请求为了保持数据的一致性也会将这段时间的命令缓存进另一个缓冲区(aof_rewrite_buf),等到重写完毕再将该部分的缓存写入AOF文件。
AOF 的优点:
- 更高的数据安全性:AOF 可以配置不同的 fsync 策略(每秒、每写入、不同步),以满足不同数据安全性需求。
- 人类可读性:AOF 文件记录的是 Redis 命令,因此可以直接查看和理解。
AOF 的缺点:
- 文件尺寸较大:由于 AOF 记录了所有的写入命令,其文件尺寸通常比 RDB 文件大。
- 重写和恢复速度较慢:由于文件尺寸较大,AOF 重写和数据恢复过程可能会更耗时。
RDB 和 AOF 的区别及取舍
- 持久化机制:RDB 使用快照方式生成二进制文件,而 AOF 通过记录写入命令进行持久化。
- 数据安全性:AOF 提供了更高的数据安全性,因为它可以实时记录数据变更,而 RDB 只能定期生成快照。
- 文件尺寸和恢复速度:RDB 文件尺寸较小,恢复速度较快;AOF 文件尺寸较大,恢复速度较慢。
- 可读性:AOF 文件具有较好的可读性,因为它记录的是 Redis 命令。
根据具体的应用场景和需求,可以选择使用 RDB、AOF 或两者同时使用。如果数据安全性要求较高,可以选择 AOF;如果对恢复速度有较高要求,可以选择 RDB。同时使用两者可以在一定程度上提高数据安全性和恢复速度,但需要权衡系统资源和复杂性。
其实 Redis 的这整个设计看起来可以说是一个标准的复制状态机的应用,日志 + 快照,我们可以看到 MySQL 也有类似的设计,redo log 是它的日志,而 bing log 是它的快照。