3.3Rewrite机制
随着使用时间的推移,AOF 文件会越来越大。为了防止 AOF 文件由于太大而占用大量的磁盘空间,降低性能,Redis 引入了 Rewrite 机制来对 AOF 文件进行压缩。
(1)何为rewrite
所谓Rewrite其实就是对AOF文件进行重写整理。当Rewrite开启后,主进程redis-server创建出一个子进程bgrewriteaof,由该子进程完成rewrite过程。其首先对现有aof文件进行rewrite计算,将计算结果写入到一个临时文件,写入完毕后,再rename该临时文件为原aof文件名,覆盖原有文件。
(2)rewrite计算
rewrite计算也称为rewrite策略。rewrite计算遵循以下策略:
- 读操作命令不写入文件
- 无效命令不写入文件
- 过期数据不写入文件
- 多条命令合并写入文件
(3)手动开启rewrite
Rewrite过程的执行有两种方式。一种是通过bgrewriteaof命令手动开启,一种是通过设置条件自动开启。
以下是手动开启方式:
该命令会使主进程redis-server创建出一个子进程bgrewriteaof,由该子进程完成rewrite过程。而在 rewrite 期间,redis-server仍是可以对外提供读写服务的。
(4)自动开启rewrite
手动方式需要人办干预,所以一般采用自动方式。由于 Rewrite 过程是一个计算过程,需要消耗大量系统资源,会降低系统性能。所以,Rewrite 过程并不是随时随地任意开启的,而是通过设置一些条件,当满足条件后才会启动,以降低对性能的影响。
下面是配置文件中对于 Rewrite 自动启动条件的设置。
- auto-aof-rewrite-percentage:开启rewrite的增大比例,默认100%。指定为0,表示禁用自动rewrite。
- auto-aof-rewrite-min-size:开启rewrite的AOF文件最小值,默认64M。该值的设置主要是为了防止小AOF文件被rewrite,从而导致性能下降。
自动重写AOF文件。当AOF日志文件大小增长到指定的百分比时,Redis主进程redis-server会fork出一个子进程 bgrewriteaof来完成rewrite过程。
其工作原理如下:Redis会记住最新rewrite后的AOF文件大小作为基本大小,如果从主机启动后就没有发生过重写,则基本大小就使用启动时AOF的大小。
如果当前AOF文件大于基本大小的配置文件中指定的百分比阈值,且当前AOF文件大于配置文件中指定的最小阈值,则会触发rewrite。
3.4AOF优化配置
(1)appendfsync
当客户端提交写操作命令后,该命令就会写入到 aof_buf 中,而 aof_buf 中的数据持久化到磁盘 AOF 文件的过程称为数据同步。
何时将 aof_buf 中的数据同步到 AOF 文件?采用不同的数据同步策略,同时的时机是不同的,有三种策略:
- always:写操作命令写入 aof_buf 后会立即调用 fsync()系统函数,将其追加到 AOF 文件。该策略效率较低,但相对比较安全,不会丢失太多数据。最多就是刚刚执行过的写操作在尚未同步时出现宕机或重启,将这一操作丢失。
- no:写操作命令写入 aof_buf 后什么也不做,不会调用 fsync()函数。而将 aof_buf 中的数据同步磁盘的操作由操作系统负责。Linux 系统默认同步周期为 30 秒。效率较高。
- everysec:默认策略。写操作命令写入 aof_buf 后并不直接调用 fsync(),而是每秒调用一次 fsync()系统函数来完成同步。该策略兼顾到了性能与安全,是一种折中方案。
(2)no-appendfsync-on-rewrite
该属性用于指定,当AOF fsync策略设置为always或everysec,当主进程创建了子进程正在执行bgsave或 bgrewriteaof时,主进程是否不调用fsync()来做数据同步。设置为no,双重否定即肯定,主进程会调用fsync()做同步。而yes则不会调用fsync()做数据同步。
如果调用fsync(),在需要同步的数据量非常大时,会阻塞主进程对外提供服务,即会存在延迟问题。如果不调用 fsync(),则 AOF fsync 策略相当于设置为了no,可能会存在30秒数据丢失的风险。
(3)aof-rewrite-incremental-fsync
当bgrewriteaof在执行过程也是先将rewrite计算的结果写入到了aof_rewrite_buf缓存中,然后当缓存中数据达到一定量后就会调用fsync()进行刷盘操作,即数据同步,将数据写入到临时文件。该属性用于控制 fsync()每次刷盘的数据量最大不超过4MB。这样可以避免由于单次刷盘量过大而引发长时间阻塞。
(4)aof-load-truncated
在进行 AOF 持久化过程中可能会出现系统突然宕机的情况,此时写入到 AOF 文件中的最后一条数据可能会不完整。当主机启动后,Redis 在 AOF 文件不完整的情况下是否可以启动,取决于属性 aof-load-truncated 的设置。其值为:
- yes:AOF 文件最后不完整的数据直接从 AOF 文件中截断删除,不影响 Redis 的启动。
- no:AOF 文件最后不完整的数据不可以被截断删除,Redis 无法启动。
(5)aof-timestamp-enabeld
该属性设置为yes则会开启在AOF文件中增加时间戳的显示功能,可方便按照时间对数据进行恢复。但该方式可能会与AOF解析器不兼容,所以默认值为no,不开启。
3.5AOF持久化过程
AOF 详细的持久化过程如下:
-
Redis 接收到的写操作命令并不是直接追加到磁盘的 AOF 文件的,而是将每一条写命令按照 redis 通讯协议格式暂时添加到 AOF 缓冲区 aof_buf。
-
根据设置的数据同步策略,当同步条件满足时,再将缓冲区中的数据一次性写入磁盘的AOF 文件,以减少磁盘 IO 次数,提高性能。
-
当磁盘的 AOF 文件大小达到了 rewrite 条件时,redis-server 主进程会 fork 出一个子进程bgrewriteaof,由该子进程完成 rewrite 过程。
-
子进程 bgrewriteaof 首先对该磁盘 AOF 文件进行 rewrite 计算,将计算结果写入到一个临时文件,全部写入完毕后,再 rename 该临时文件为磁盘文件的原名称,覆盖原文件。
-
如果在 rewrite 过程中又有写操作命令追加,那么这些数据会暂时写入 aof_rewrite_buf缓冲区。等将全部 rewrite 计算结果写入临时文件后,会先将 aof_rewrite_buf 缓冲区中的数据写入临时文件,然后再 rename 为磁盘文件的原名称,覆盖原文件。
4.RDB 与 AOF 对比
4.1RDB优势与不足
(1)RDB优势
- RDB 文件较小
- 数据恢复较快
(2)RDB不足
- 数据安全性较差
- 写时复制会降低性能
- RDB 文件可读性较差
4.2AOF优势与不足
(1)AOF优势
- 数据安全性高
- AOF 文件可读性强
(2)AOF不足
- AOF 文件较大
- 写操作会影响性能
- 数据恢复较慢
5.持久化技术选型
- 官方推荐使用 RDB 与 AOF 混合式持久化。
- 若对数据安全性要求不高,则推荐使用纯 RDB 持久化方式。
- 不推荐使用纯 AOF 持久化方式。
- 若 Redis 仅用于缓存,则无需使用任何持久化技术。