Redis 提供了两种持久化方式,即 RDB(Redis Database)和 AOF(Append-Only File)。
RDB
RDB 持久化是 Redis 的默认持久化方式。它将 Redis 的数据集以二进制格式保存到磁盘上的一个文件中。RDB 持久化适用于执行周期性备份的场景。RDB 文件是通过压缩(可以配置 rdbcompression 参数禁用压缩以节省 CPU 资源)的二进制格式,更加紧凑以节省空间。
- 触发机制:管理员可以根据配置文件设置触发 RDB 持久化的方式,例如在指定的时间间隔内、在指定的修改次数后、或同时满足时间和修改次数的条件下触发。
- 优点:RDB 持久化对性能影响较小,生成的 RDB 文件紧凑且易于备份和恢复。
- 缺点:RDB 持久化会将数据保存到一个快照文件中,因此在发生故障时可能会丢失最后一次快照之后的数据。
快照原理
Redis 会默认将备份的快照文件存储在 Redis 当前进程工作目录中的 dump.rbd 文件中,可以配置 dir 和 dirfilename 两个参数分别指定快照的存储路径和文件名。
创建快照的步骤:
- fork 复制当前 redis 进程的一个副本
- 父进程继续接受客户端的请求并处理,子进程开始将内存中的数据写入硬盘中的临时文件
- 写入完毕,会使用临时文件替换目录下的 RDB 文件
在执行 fork 函数时,类 unix 操作系统会使用写时拷贝策略。所以新的 RDB 文件存储的时执行 fork 函数那一刻的内存数据。 关于写时拷贝(Copy-On-Write,COW) 在使用写时拷贝的情况下,当多个进程或线程共享同一份内存数据时,它们实际上共享同一个物理内存页。这意味着在一开始,这些进程或线程都指向相同的内存页。当其中一个进程或线程尝试修改这个共享的内存页时,才会进行实际的拷贝操作。这个操作会将要修改的内存页复制一份,使得修改操作只影响到修改操作的那个进程或线程,而不会影响其他共享该内存页的进程或线程。 写时拷贝的优点是在数据没有发生写操作之前,多个进程或线程可以共享同一份内存数据,避免了不必要的内存复制。这对于需要共享大量数据或频繁进行复制操作的情况下,可以提高性能和节省内存空间。
自动快照机制
在 Redis 中,可以通过在配置文件中设置 save
指令来配置自动触发快照的规则。save
指令的格式如下:
save <seconds> <changes>
其中,<seconds>
表示时间间隔,单位是秒,指定了多长时间内如果发生了至少 <changes>
次修改操作,则触发快照。
例如,以下是一些示例配置规则:
代码语言:javascript复制save 900 1 # 如果在900秒(15分钟)内至少有1个键被修改,则触发快照
save 60 10000 # 如果在60秒内至少有10000个键被修改,则触发快照
save 300 5 # 如果在300秒(5分钟)内至少有5个键被修改,则触发快照
在上述示例中,Redis 会根据指定的时间间隔和修改次数来判断是否触发快照生成。当满足任意一个配置规则时,Redis 将自动执行快照操作。
需要注意的是,配置多个 save
指令会形成一个规则列表。当 Redis 执行快照时,会按照规则列表的顺序进行判断。因此,应该将频率较低、更保守的规则放在列表的前面,而将频率较高、更宽松的规则放在列表的后面。
手动快照机制
SAVE
当执行 SAVE
命令时,Redis 会阻塞主进程,将数据集以二进制格式保存到磁盘上的一个 RDB 文件中。在生成快照期间,Redis 不能处理其他命令请求,直到快照过程完成。
SAVE
命令在快照生成期间对 Redis 的性能会有一定的影响,因此,不建议在生产环境中使用 SAVE,一般情况下建议使用 BGSAVE
命令进行快照生成。
BGSAVE
BGSAVE
命令用于在后台异步执行生成 Redis 快照。当执行 BGSAVE
命令时,Redis 会启动一个子进程来生成快照,而不会阻塞主进程。在子进程生成快照的同时,Redis 主进程可以继续处理其他命令请求。
LASTSAVE
命令用于获取最后一次生成快照的时间戳。执行 LASTSAVE
命令后,Redis 会返回一个表示最后一次生成快照时间的 UNIX 时间戳。
FLUSHALL
执行 FLUSHALL
命令将删除当前正在使用的所有数据库中的所有键值对。这个命令会导致所有数据被永久删除。FLUSHALL
命令是一个原子操作,即要么全部清空成功,要么全部失败。在执行期间,Redis 将阻塞其他命令的执行。
如果当前配置了自动快照条件,那么不论清空过程是否达到快照条件,都会进行快照。
主从模式下的复制
关于主从模式和复制的内容应该单独讲,所以这里就不讨论了
AOF
AOF 持久化以日志的形式记录 Redis 服务器所执行的写操作,将这些写操作追加到文件的末尾。当 Redis 重新启动时,可以通过重新执行这些写操作来还原数据集。在配置文件中找到 appendonly
的配置项,配置 appendonly yes 启用配置。
- 触发机制:管理员可以根据配置文件设置 AOF 持久化的触发方式,例如每次写操作、每秒同步等。
- 优点:AOF 持久化提供了更高的数据安全性,因为可以通过重放 AOF 日志来恢复数据。此外,AOF 文件是可读的,可以用于故障排查和数据分析。
- 缺点:相比 RDB 持久化,AOF 持久化文件更大,恢复速度可能较慢,对于大的写操作负载可能会影响性能。
AOF 的实现
AOF 文件是一个文本文件,其中包含了 Redis 接收到的每个写操作的命令。每个命令都以 Redis 协议格式进行编码,并追加到 AOF 文件的末尾。
下面是一个示例,展示了在 AOF 文件中可能包含的命令:
代码语言:javascript复制*3rn$3rnSETrn$5rnmykeyrn$7rnmyvaluern
*2rn$3rnGETrn$5rnmykeyrn
*4rn$4rnHMSETrn$6rnmyhashrn$2rna1rn$3rnvalrn$2rna2rn$3rn123rn
每个命令由多个部分组成,以 rn
(CRLF)作为分隔符。以下是命令的结构:
*3rn
:表示命令由三个参数组成。$3rnSETrn
:表示第一个参数是字符串,长度为 3,值为”SET”。$5rnmykeyrn
:表示第二个参数是字符串,长度为 5,值为”mykey”。$7rnmyvaluern
:表示第三个参数是字符串,长度为 7,值为”myvalue”。
在 AOF 文件中,每个命令都按照此格式(redis 的通信协议格式)记录。当 Redis 重新启动时,它会逐行读取 AOF 文件中的命令,并将其重新执行,以还原数据。
需要注意的是,AOF 文件是追加写入的,因此它会随着每个新的写操作而增长。为了保护数据的完整性,可以根据需要选择合适的 AOF 同步策略,确保将写操作同步到磁盘。
AOF 的优化
如果有这样三条命令,实际上对于恢复数据来讲,前两条记录是无用的。随着执行的命令越来越多,AOF 文件也越来越大,即使内存中的数据可能并不多。
代码语言:javascript复制SET key 1
SET key 2
SET key 3
redis 能够自动优化 AOF 文件,每当达到一定条件 redis 就会重写 AOF 文件,这个条件可以在配置文件中配置:
代码语言:javascript复制1、auto-aof-rewrite-percentage:该配置项表示当AOF文件的大小超过上一次AOF重写(如果没有重写则以启动时大小为标准)之后的大小的一定百分比时,Redis会自动触发AOF重写。默认值为100,即AOF文件大小超过上一次重写大小的100%时触发重写。
2、auto-aof-rewrite-min-size:该配置项表示当AOF文件的大小超过一定字节数时,Redis会自动触发AOF重写,无论是否超过了上一次AOF重写之后的大小。默认值为64MB。
AOF 重写通过读取当前数据集的内存状态,并以更紧凑的方式重新写入 AOF 文件,去除了冗余的命令和操作。AOF 重写不会影响正在运行的 Redis 实例的正常操作,它是在后台进行的。
AOF 重写的过程如下:
- Redis 会创建一个后台进程,该进程负责扫描当前数据集的所有写操作,并生成一个新的 AOF 文件。
- 在生成新的 AOF 文件时,只记录了重写期间的写操作,不包括旧 AOF 文件中的命令。
- 重写完成后,Redis 会用新的 AOF 文件替换旧的 AOF 文件。
硬盘同步
事实上,由于 IO 缓存机制,进程的 IO 操作并不会立马体现在磁盘内容上。操作系统会将 IO 操作中的数据暂时存储在内存中的缓存中,并在适当的时机将其刷新到磁盘上。IO 缓存的存在可以提高 IO 性能,因为内存中的读取和写入比磁盘访问要快得多。通过将多个 IO 操作合并成更大的块,可以减少磁盘访问的次数,从而提高效率。这种方式下,进程可以更快地完成 IO 操作并继续执行后续的任务。
然而,IO 缓存也引入了数据持久性和一致性的问题。如果系统发生故障(如断电),尚未刷新到磁盘的缓存数据可能会丢失。这种情况造成的损失对于使用 redis 写入 AOF 文件实现持久化的应用时无法容忍的,这就需要 redis 再写入 AOF 文件后立即将缓存同步到磁盘中。
在 redis 中, appendfsync
配置项用于控制 AOF(Append-Only File)文件的同步策略,即何时将 AOF 缓冲区的数据同步到磁盘。
在配置文件中,有三个可选的 appendfsync
选项:
appendfsync always
:表示每次执行写操作时都会将 AOF 缓冲区的数据立即同步到磁盘。这是最安全的选项,因为它可以确保每个写操作都持久化到磁盘,但也会对性能产生较大的影响,因为每次写操作都需要等待磁盘的响应。appendfsync everysec
:表示每秒将 AOF 缓冲区的数据同步到磁盘一次。这是默认的选项,它在性能和数据安全之间取得了一种平衡。Redis 会将 AOF 缓冲区的数据积累到一定程度,然后每秒同步一次到磁盘,这样可以提高性能并保证一定程度的数据持久化。appendfsync no
:表示完全依赖操作系统进行数据同步,即不强制要求将 AOF 缓冲区的数据立即同步到磁盘。这是最高性能的选项,因为写操作不会等待磁盘的响应,但也是最不安全的选项,因为在发生系统崩溃等情况时可能会导致数据丢失。
操作系统提供了同步写(synchronous write)和异步写(asynchronous write)两种方式。
- 同步写(Synchronous Write):在同步写模式下,每次 IO 操作完成后,操作系统会立即将数据写入磁盘并进行同步操作,确保数据的持久性和一致性。这意味着写操作会阻塞,直到数据被写入磁盘为止,但可以提供更高的数据可靠性。
- 异步写(Asynchronous Write):在异步写模式下,操作系统会将数据写入磁盘的操作交给后台线程或其他机制处理,而不会阻塞进程的执行。这样可以提高 IO 操作的性能,但也会增加数据丢失的风险,因为在数据被刷新到磁盘之前发生故障,尚未写入磁盘的数据可能会丢失。
因此,在涉及到数据持久性和一致性的场景中,可以根据需求选择合适的同步或异步写模式,以平衡性能和数据可靠性的需求。
混合持久化
可以同时使用 RDB 和 AOF 来进行持久化。
同时启用 RDB 和 AOF,Redis 可以将数据保存到磁盘上的两个不同文件中。RDB 会定期创建快照,将内存中的数据保存到磁盘上的 RDB 文件中,而 AOF 会记录每个写操作的指令,将其追加到 AOF 文件中。
同时使用 RDB 和 AOF 的好处包括:
- 数据安全性:RDB 和 AOF 都提供了数据持久化的机制,可以将数据写入磁盘以保证数据的安全性。如果其中一种持久化方式发生故障,另一种方式仍然可以用于恢复数据。
- 灵活的恢复选项:使用混合持久化可以根据需要选择不同的恢复策略。RDB 快照适用于快速恢复,因为它可以在较短的时间内加载大量的数据。而 AOF 文件记录了写操作的历史记录,可以提供更精确的恢复点。
- 性能优化:RDB 快照对于大规模的数据恢复来说效率更高,而 AOF 文件对于重放操作日志来说更高效。通过同时使用 RDB 和 AOF,可以根据应用程序的需求进行性能优化。
------本页内容已结束,喜欢请分享------