- 浏览: 141270 次
文章分类
最新评论
除了前面提到的 RDB 持久化功能外,Redis 还提供了 AOF(Append Only File)持久化。与 RDB 通过保存数据库中的键值对来记录数据库状态不同,AOF 是通过保存 Redis 服务器所执行的写命令来记录数据库状态的。
被写入 AOF 文件的所有命令都是以 Redis 的命令请求协议格式保存的,这是一种纯文本格式,可以直接打开观察其内容。例如,下图是在 0 号数据库中执行了 SET、SADD 和 RPUSH 命令后保存的 AOF 文件内容。
其中,除了用于指定数据库的 SELECT 命令是服务器自动添加的之外,其他的都是之前通过客户端发送的命令。
AOF 持久化功能的实现可以分为命令追加、文件写入和文件同步三个步骤。
当 AOF 持久化功能打开时,服务器在执行完一个写命令后,就会以协议格式将这个命令追加到服务器状态的 aof_buf 缓冲区中。
Redis 的服务器进程就是一个事件循环,其中的文件事件负责接收客户端的命令请求,以及向客户端发送命令回复,而时间事件则负责执行像 serverCron 函数这样需要定时运行的函数。因为服务器在处理文件事件时可能会执行写命令,使得一些内容被追加到 aof_buf 缓冲区里面,所以服务器每结束一个事件循环之前,都会调用 flushAppendOnlyFile 函数,以考虑是否需要将 aof_buf 缓冲区中的内容写入和保存到 AOF 文件里面。这个过程可以使用以下伪代码表示。
flushAppendOnlyFile 函数的行为由服务器配置的 appendfsync 选项的值(默认为 everysec)来决定,各个不同值产生的行为如下表所示。
其中:
当 appendfsync 的值为 always 时,服务器在每个事件循环都要将 aof_buf 缓冲区的内容写入并等待同步到 AOF 文件,所以效率是最慢的。但从安全性来说,它却是最安全的,因为即使出现故障停机,AOF 持久化也只会丢失一个事件循环中所产生的命令数据。
当 appendfsync 的值为 everysec 时,服务器在每个事件循环都要将 aof_buf 缓冲区中的内容写入到 AOF 文件,但每隔一秒才在子线程中对 AOF 文件进行一次同步,因此这种方式最多丢失一秒钟的命令数据。
当 appendfsync 的值为 no 时,服务器同样在每个事件循环都要将 aof_buf 缓冲区中的内容写入到 AOF 文件,不过至于何时对 AOF 文件进行同步,则由操作系统自行控制。因此这种方式的 AOF 写入速度通常是最快的,但由于会在系统缓存中积累一段时间的写入数据,所以其单次同步时长通常是最长的,它最多丢失上次同步 AOF 文件之后的所有写命令数据。
由于 AOF 文件里面包含了重建数据库状态所需的所有写命令,所以服务器只要读入并重新执行一遍 AOF 文件里面保存的写命令,就可以还原服务器关闭之前的数据库状态。Redis 读取 AOF 文件并还原数据库状态的流程如下。
注意,这里之所以创建一个不带网络连接的伪客户端(fake client),是因为 Redis 的命令只能在客户端上下文中执行,而载入 AOF 文件时所用的命令直接来源于 AOF 文件而不是网络连接,所以才创建一个伪客户端来达到普通客户端执行命令的效果。
根据上面所述易知,AOF 文件的体积会随着服务器运行时间的流逝而变得越来越大,如果不加以控制,可能会对 Redis 服务器、甚至整个宿主机造成影响,而且 AOF 文件的体积越大,也表示使用 AOF 文件来进行数据还原所需的时间也就越多。
为了解决 AOF 文件体积膨胀过快的问题,Redis 提供了 AOF 文件重写功能。不过虽然这个功能被称为“AOF 文件重写”,但实际上它并不需要对现有的 AOF 文件进行任何的读取、分析或者写入操作,而是通过直接读取数据库中的键值对,并创建一个新的 AOF 文件替代现有的 AOF 文件来实现的。新旧两个 AOF 文件所保存的数据库状态相同,但新 AOF 文件不会包含冗余命令(比如,对于多个连续的 LPOP 列表操作,无需记录多条 LPOP 命令操作,而只需用一条命令记录列表的最终状态即可),所以其体积往往比旧 AOF 文件的要小得多。
要注意的是,在实际中,为了避免执行命令时造成客户端输入缓冲区溢出,重写程序在处理列表、哈希表、集合和有序集合这四种可能含有多个元素的键时,会先检查键所包含的元素数量,如果超过了 redis.h/REDIS_AOF_REWRITE_ITEMS_PER_CMD 常量(一般为 64)的值,那么重写程序将使用多条命令来记录键的值,而不单单使用一条命令。
最后,因为 AOF 重写程序通常会进行大量的写入操作,所以为了避免阻塞服务器,Redis 会将其放到子进程里执行。不过虽然使用子进程而非线程可以在避免使用锁的情况下保证数据的安全性,但这却需要解决一个问题,即子进程在进行 AOF 重写期间,服务器进程(父进程)接收到的新的命令可能会修改现有的数据库状态,从而使得与子进程利用父进程的数据副本重写后的 AOF 文件所保存的数据库状态不一致。因此,为了解决这种数据不一致问题,Redis 服务器设置了一个 AOF 重写缓冲区,它会在服务器创建子进程之后开始使用:当 Redis 服务器执行完一个写命令后,会同时将这个写命令追加到 AOF 缓冲区和 AOF 重写缓冲区。
当子进程完成 AOF 重写工作后,会向父进程发送一个信号,父进程则会在相应的信号处理函数中执行以下工作:
1)将 AOF 重写缓冲区中的所有内容写入到 AOF 文件中,这时 AOF 文件所保存的数据库状态将和服务器当前的数据库状态一致。
2)对新的 AOF 文件进行改名,原子地覆盖现有的 AOF 文件,完成新旧两个 AOF 文件的替换。
这就是 AOF 后台重写,也即是 BGREWRITEAOF 命令的实现原理。
参考书籍:《Redis 设计与实现》第 11 章——AOF 持久化。
被写入 AOF 文件的所有命令都是以 Redis 的命令请求协议格式保存的,这是一种纯文本格式,可以直接打开观察其内容。例如,下图是在 0 号数据库中执行了 SET、SADD 和 RPUSH 命令后保存的 AOF 文件内容。
其中,除了用于指定数据库的 SELECT 命令是服务器自动添加的之外,其他的都是之前通过客户端发送的命令。
AOF 持久化功能的实现可以分为命令追加、文件写入和文件同步三个步骤。
当 AOF 持久化功能打开时,服务器在执行完一个写命令后,就会以协议格式将这个命令追加到服务器状态的 aof_buf 缓冲区中。
struct redisServer{ // ... sds aof_buf; // AOF 缓冲区 // ... };
Redis 的服务器进程就是一个事件循环,其中的文件事件负责接收客户端的命令请求,以及向客户端发送命令回复,而时间事件则负责执行像 serverCron 函数这样需要定时运行的函数。因为服务器在处理文件事件时可能会执行写命令,使得一些内容被追加到 aof_buf 缓冲区里面,所以服务器每结束一个事件循环之前,都会调用 flushAppendOnlyFile 函数,以考虑是否需要将 aof_buf 缓冲区中的内容写入和保存到 AOF 文件里面。这个过程可以使用以下伪代码表示。
def eventLoop(): while True: processFileEvents() # 处理文件事件,接收命令请求以及发送命令回复 processTimeEvents() # 处理时间事件 flushAppendOnlyFile() # 考虑是否要将 aof_buf 中的内容保存到 AOF 文件
flushAppendOnlyFile 函数的行为由服务器配置的 appendfsync 选项的值(默认为 everysec)来决定,各个不同值产生的行为如下表所示。
其中:
当 appendfsync 的值为 always 时,服务器在每个事件循环都要将 aof_buf 缓冲区的内容写入并等待同步到 AOF 文件,所以效率是最慢的。但从安全性来说,它却是最安全的,因为即使出现故障停机,AOF 持久化也只会丢失一个事件循环中所产生的命令数据。
当 appendfsync 的值为 everysec 时,服务器在每个事件循环都要将 aof_buf 缓冲区中的内容写入到 AOF 文件,但每隔一秒才在子线程中对 AOF 文件进行一次同步,因此这种方式最多丢失一秒钟的命令数据。
当 appendfsync 的值为 no 时,服务器同样在每个事件循环都要将 aof_buf 缓冲区中的内容写入到 AOF 文件,不过至于何时对 AOF 文件进行同步,则由操作系统自行控制。因此这种方式的 AOF 写入速度通常是最快的,但由于会在系统缓存中积累一段时间的写入数据,所以其单次同步时长通常是最长的,它最多丢失上次同步 AOF 文件之后的所有写命令数据。
由于 AOF 文件里面包含了重建数据库状态所需的所有写命令,所以服务器只要读入并重新执行一遍 AOF 文件里面保存的写命令,就可以还原服务器关闭之前的数据库状态。Redis 读取 AOF 文件并还原数据库状态的流程如下。
注意,这里之所以创建一个不带网络连接的伪客户端(fake client),是因为 Redis 的命令只能在客户端上下文中执行,而载入 AOF 文件时所用的命令直接来源于 AOF 文件而不是网络连接,所以才创建一个伪客户端来达到普通客户端执行命令的效果。
根据上面所述易知,AOF 文件的体积会随着服务器运行时间的流逝而变得越来越大,如果不加以控制,可能会对 Redis 服务器、甚至整个宿主机造成影响,而且 AOF 文件的体积越大,也表示使用 AOF 文件来进行数据还原所需的时间也就越多。
为了解决 AOF 文件体积膨胀过快的问题,Redis 提供了 AOF 文件重写功能。不过虽然这个功能被称为“AOF 文件重写”,但实际上它并不需要对现有的 AOF 文件进行任何的读取、分析或者写入操作,而是通过直接读取数据库中的键值对,并创建一个新的 AOF 文件替代现有的 AOF 文件来实现的。新旧两个 AOF 文件所保存的数据库状态相同,但新 AOF 文件不会包含冗余命令(比如,对于多个连续的 LPOP 列表操作,无需记录多条 LPOP 命令操作,而只需用一条命令记录列表的最终状态即可),所以其体积往往比旧 AOF 文件的要小得多。
要注意的是,在实际中,为了避免执行命令时造成客户端输入缓冲区溢出,重写程序在处理列表、哈希表、集合和有序集合这四种可能含有多个元素的键时,会先检查键所包含的元素数量,如果超过了 redis.h/REDIS_AOF_REWRITE_ITEMS_PER_CMD 常量(一般为 64)的值,那么重写程序将使用多条命令来记录键的值,而不单单使用一条命令。
最后,因为 AOF 重写程序通常会进行大量的写入操作,所以为了避免阻塞服务器,Redis 会将其放到子进程里执行。不过虽然使用子进程而非线程可以在避免使用锁的情况下保证数据的安全性,但这却需要解决一个问题,即子进程在进行 AOF 重写期间,服务器进程(父进程)接收到的新的命令可能会修改现有的数据库状态,从而使得与子进程利用父进程的数据副本重写后的 AOF 文件所保存的数据库状态不一致。因此,为了解决这种数据不一致问题,Redis 服务器设置了一个 AOF 重写缓冲区,它会在服务器创建子进程之后开始使用:当 Redis 服务器执行完一个写命令后,会同时将这个写命令追加到 AOF 缓冲区和 AOF 重写缓冲区。
当子进程完成 AOF 重写工作后,会向父进程发送一个信号,父进程则会在相应的信号处理函数中执行以下工作:
1)将 AOF 重写缓冲区中的所有内容写入到 AOF 文件中,这时 AOF 文件所保存的数据库状态将和服务器当前的数据库状态一致。
2)对新的 AOF 文件进行改名,原子地覆盖现有的 AOF 文件,完成新旧两个 AOF 文件的替换。
这就是 AOF 后台重写,也即是 BGREWRITEAOF 命令的实现原理。
参考书籍:《Redis 设计与实现》第 11 章——AOF 持久化。
发表评论
-
Lua 脚本
2019-10-07 19:49 666Redis 2.6 版本开始引入对 Lua 脚 ... -
Redis事务的实现
2019-09-22 18:56 466Redis 事务是 ... -
Redis集群之复制、故障转移及消息实现
2019-09-14 21:04 497在Redis集群 ... -
Redis集群实现原理
2019-09-14 12:19 662Redis 集群是 Redis 提供的分布式数 ... -
sentinel 系统介绍
2019-08-04 18:35 500Sentinel(哨兵)是 Redis 的高可 ... -
数据库复制
2019-07-13 22:02 364在连接到一 ... -
redis 客户端实现
2019-06-02 15:06 371Redis 服务器是典型的一对多服务器程序,通 ... -
RDB 文件结构
2019-04-27 12:10 576在RDB 持久化一节中,我们对 RDB 持久化 ... -
RDB 持久化
2019-04-14 17:20 419RDB 持久化功能可以将 Redis 在某个时 ... -
Redis 数据库通知功能的实现
2019-04-07 11:56 1282Reids 数据库通知功能可以让客户端通过订阅 ... -
数据库实现
2019-03-24 13:58 438Redis 服务器将其所有的数据库都保存在 r ... -
Redis 五种对象
2019-01-20 11:13 361阅读本节前需要阅读 Redis 对象系统概览一 ... -
Redis 对象系统概览
2019-01-06 13:10 777前面介绍了 Redis 中用到的所有主要数据结 ... -
整数集合与压缩列表
2018-12-09 21:19 592在 Redis 中,当一 ... -
跳跃表在 Redis 中的应用
2018-08-23 16:30 2023前提申明,因篇幅 ... -
字典实现
2018-08-20 15:49 565字典在 Redis 中的应用相当广泛,如 Redis ... -
redis 字符串和列表实现
2018-08-08 16:41 748Redis 虽说由 C 语言 ...
相关推荐
从上面的描述中我们可以看到,AOF持久化的工作原理是在每次命令执行之后,将命令追加到AOF文件的末尾。这种方式虽然可以减少数据丢失,但也存在一些问题。由于操作系统通常会使用缓冲区来提高文件写入的效率,因此...
在 Redis 中,AOF(Append Only File)持久化策略是数据保存的一种方式,它记录了所有对数据库进行修改的命令,确保即使在服务器崩溃后也能恢复数据。本文将深入探讨 AOF 持久化策略及其配置文件。 首先,我们需要...
redis配置文件aof持久化方式,修改了redis密码为123456
Redis AOF持久化.flv
Table of Contents generated with DocToc11.1 AOF持久化的实现命令追加AOF文件的写入与同步11.2 AOF文件的载
部署安装Redis及RDB、AOF持久化验证.md
2. **持久化**:尽管 Redis 是一个内存数据库,但它提供了持久化机制,可以将内存中的数据保存到磁盘,防止数据丢失。 3. **支持事务**:Redis 支持简单的事务功能,可以保证操作的原子性。 4. **丰富的数据类型**:...
Redis 持久化是确保数据安全的重要机制,它提供了两种主要的方法:RDB(Redis Database)和 AOF(Append Only File)。RDB 是一种快照式的持久化方式,而 AOF 则记录每次写操作的日志。 RDB 持久化在特定条件下将...
AOF持久化AOF(Append Only File)持久化是一种基于日志的持久化方式。Redis将所有的写操作命令记录到一个AOF文件中。当Redis重新启动时,可以通过重放AOF文件中的命令来恢复数据。AOF持久化提供了更高的数据安全性...
AOF持久化方案是指记录每一个对Redis数据库进行修改的命令到一个日志文件中,并在Redis重启时通过回放这些命令来恢复数据。AOF能够提供更高的数据安全性,可以通过配置选择不同的fsync策略,如每次写入后同步到磁盘...
为了保证数据的安全性和持久性,Redis 提供了两种主要的持久化机制:RDB 快照(Redis Database Backup)和 AOF(Append Only File)。本文将详细介绍这两种持久化方式的原理、配置方法及其各自的优缺点。 #### RDB ...
- `appendonly`: 是否启用AOF持久化,默认为no。 - `appendfsync`: 写入策略,默认为everysec,表示每秒同步一次。 - `auto-aof-rewrite-percentage` 和 `auto-aof-rewrite-min-size`: 控制何时自动触发AOF重写。 #...
AOF持久化则是关注于数据的操作过程,它以日志的形式记录数据变更,即记录被执行的写命令,因此AOF文件是可读的。当Redis重启时,AOF文件可以被重新执行来恢复数据。AOF持久化提供了三种不同的fsync策略:no、...
redis主从复制 RDB/AOF持久化 数据类型-附件资源
Redis的RDB和AOF持久化机制分别提供了不同的数据安全保障。RDB通过定期快照,适合对数据一致性要求不那么高的场景,而AOF则更适合需要保证数据完整性的应用。选择合适的持久化策略,需要权衡数据丢失的风险、恢复...
- RDB持久化机制: ...- AOF持久化机制: - AOF默认关闭,需要将appendonly yes手动开启 - RDB默认持久化日志文件,将每次写操作的命令持久化到本地文件中,在持久化和读取持久化文件时,相对RDB较慢
Redis 是一个高性能的 NoSQL 数据库,为了确保数据的安全性和可靠性,Redis 提供了多种持久化机制,分别是 RDB 持久化方式和 AOF 持久化方式。本文将对 Redis 持久化机制进行详细的介绍和比较。 RDB 持久化方式 ...
与RDB相比,AOF持久化能够提供更高的数据安全性,因为每条写操作都被记录下来,即使在断电的情况下也能够通过回放AOF文件来恢复数据。 ##### 3.2 AOF 持久化策略 - **always**:每次有写操作发生时都同步到磁盘,...