前言
Redis 是内存数据库,数据都是存储在内存中,为了避免进程退出导致数据的永久丢失,需要定期将 Redis 中的数据以数据或命令的形式从内存保存到本地磁盘。当下次 Redis 重启时,利用持久化文件进行数据恢复。Redis 提供了 RDB 和 AOF 两种持久化机制,前者将当前的数据保存到磁盘,后者则是将每次执行的写命令保存到磁盘(类似于 MySQL 的 Binlog)。本文将详细介绍 RDB 和 AOF 两种持久化方案,包括操作方法和持久化的实现原理。
正文
Redis 是一个基于 K-V 存储的数据库服务器,下面先介绍 Redis 数据库的内部构造以及 K-V 的存储形式,有助于我们更容易理解 Redis 的持久化机制。
1. Redis数据库结构
一个单机的 Redis 服务器默认情况下有 16 个数据库(0-15号),默认使用的是 0 号数据库,可以使用 SELECT 命令切换数据库。
Redis 中的每个数据库都由一个 redis.h/redisDb 结构表示,它记录了单个 Redis 数据库的键空间、所有键的过期时间、处于阻塞状态和就绪状态的键、数据库编号等等。
typedef struct redisDb { // 数据库键空间,保存着数据库中的所有键值对 dict *dict; // 键的过期时间,字典的键为键,字典的值为过期事件 UNIX 时间戳 dict *expires; // 正处于阻塞状态的键 dict *blocking_keys; // 可以解除阻塞的键 dict *ready_keys; // 正在被 WATCH 命令监视的键 dict *watched_keys; struct evictionPoolEntry *eviction_pool; // 数据库编号 int id; // 数据库的键的平均 TTL,统计信息 long long avg_ttl; } redisDb;
由于 Redis 是一个键值对数据库(key-value pairs database), 所以它的数据库本身也是一个字典,对应的结构正是 redisDb。其中,dict 指向的是一个记录键值对数据的字典,它的键是一个字符串对象,它的值则可以是字符串、列表、哈希表、集合和有序集合在内的任意一种 Redis 类型对象。 expires 指向的是一个用于记录键的过期时间的字典,它的键为 dict 中的数据库键,它的值为这个数据库键的过期时间戳,这个值以 long long 类型表示。
2. RDB持久化
RDB 持久化(也称作快照持久化)是指将内存中的数据生成快照保存到磁盘里面,保存的文件后缀是 .rdb。rdb 文件是一个经过压缩的二进制文件,当 Redis 重新启动时,可以读取 rdb 快照文件恢复数据。RDB 功能最核心的是 rdbSave 和 rdbLoad 两个函数, 前者用于生成 RDB 文件并保存到磁盘,而后者则用于将 RDB 文件中的数据重新载入到内存中:
RDB 文件是一个单文件的全量数据,很适合数据的容灾备份与恢复,通过 RDB 文件恢复数据库耗时较短,通常 1G 的快照文件载入内存只需 20s 左右。Redis 提供了手动触发保存、自动保存间隔两种 RDB 文件的生成方式,下面先介绍 RDB 的创建和载入过程。
2.1. RDB的创建和载入
2.1.1. 手动触发保存
Redis 提供了两个用于生成 RDB 文件的命令,一个是 SAVE,另一个是 BGSAVE。而触发 Redis 进行 RDB 备份的方式有两种,一种是通过 SAVE 命令、BGSAVE 命令手动触发快照生成的方式,另一种是配置保存时间和写入次数,由 Redis 根据条件自动触发保存操作。
1. SAVE命令
SAVE 是一个同步式的命令,它会阻塞 Redis 服务器进程,直到 RDB 文件创建完成为止。在服务器进程阻塞期间,服务器不能处理任何其他命令请求。
客户端命令
127.0.0.1:6379> SAVE OK
服务端日志
6266:M 15 Sep 2019 08:31:01.258 * DB saved on disk
执行 SAVE 命令后,Redis 在服务端进程(PID为6266)执行了 SAVE 操作,这个操作发生期间会一直阻塞 Redis 客户端的请求处理。
2. BGSAVE命令
BGSAVE 是一个异步式的命令,和 SAVE 命令直接阻塞服务器进程的做法不同,BGSAVE 命令会派生出一个子进程,由子进程负责创建 RDB 文件,服务器进程(父进程)继续处理客户的命令。
客户端命令
127.0.0.1:6379> BGSAVE Background saving started
服务端日志
6266:M 15 Sep 2019 08:31:22.914 * Background saving started by pid 6283 6283:C 15 Sep 2019 08:31:22.915 * DB saved on disk 6266:M 15 Sep 2019 08:31:22.934 * Background saving terminated with success
通过服务端输出的日志,可以发现Redis 在服务端进程(PID为6266)会为 BGSAVE 命令单独创建(fork)一个子进程(PID为6283),并由子进程在后台完成 RDB 的保存过程,在操作完成之后通知父进程然后退出。在整个过程中,服务器进程只会消耗少量时间在创建子进程和处理子进程信号量上面,其余时间都是待命状态。
BGSAVE 是触发 RDB 持久化的主流方式,下面给出 BGSAVE 命令生成快照的流程:
3. SAVE和BGSAVE的比较
命令 | SAVE | BGSAVE |
---|---|---|
IO类型 | 同步 | 异步 |
是否阻塞 | 全程阻塞 | fork时发生阻塞 |
复杂度 | O(n) | O(n) |
优点 | 不会消耗额外的内存 | 不阻塞客户端 |
缺点 | 阻塞客户端 | fork子进程消耗内存 |
2.1.2. 自动触发保存
因为 BGSAVE 命令可以在不阻塞服务器进程的情况下执行,所以 Redis 的配置文件 redis.conf 提供了一个 save 选项,让服务器每隔一段时间自动执行一次 BGSAVE 命令。用户可以通过 save 选项设置多个保存条件,只要其中任意一个条件被满足,服务器就会执行 BGSAVE 命令。 Redis 配置文件 redis.conf 默认配置了以下 3 个保存条件:
save 900 1 save 300 10 save 60 10000
那么只要满足以下 3 个条件中的任意一个,BGSAVE 命令就会被自动执行:
Redis 服务器会周期性地操作 serverCron 函数,这个函数每隔 100 毫秒就会执行一次,它的一项任务就是检查 save 选项所设置的保存条件是否满足,如果满足的话,就自动执行 BGSAVE 命令。
2.1.3. 启动自动载入
和使用 SAVE 和 BGSAVE 命令创建 RDB 文件不同,Redis 没有专门提供用于载入 RDB 文件的命令,RDB 文件的载入过程是在 Redis 服务器启动时自动完成的。启动时只要在指定目录检测到 RDB 文件的存在,Redis 就会通过 rdbLoad 函数自动载入 RDB 文件。
下面是 Redis 服务器启动时打印的日志,倒数第 2 条日志是在成功载入 RDB 文件后打印的。
$ redis-server /usr/local/etc/redis.conf 6266:C 15 Sep 2019 08:30:41.830 # Redis version=5.0.5, bits=64, commit=00000000, modified=0, pid=6266, just started 6266:C 15 Sep 2019 08:30:41.830 # Configuration loaded 6266:M 15 Sep 2019 08:30:41.831 * Increased maximum number of open files to 10032 (it was originally set to 256). 6266:M 15 Sep 2019 08:30:41.832 # Server initialized 6266:M 15 Sep 2019 08:30:41.833 * DB loaded from disk: 0.001 seconds 6266:M 15 Sep 2019 08:30:41.833 * Ready to accept connections
由于 AOF 文件属于增量的写入命令备份,RDB 文件属于全量的数据备份,所以更新频率比 RDB 文件的更新频率高。所以如果 Redis 服务器开启了 AOF 持久化功能,那么服务器会优先使用 AOF 文件来还原数据库状态;只有在 AOF 的持久化功能处于关闭状态时,服务器才会使用优先使用 RDB 文件还原数据库状态。
2.2. RDB的文件结构
RDB 文件是经过压缩的二进制文件,下面介绍关于RDB文件的一些细节。
2.2.1. 存储路径
SAVE 命令和 BGSAVE 命令都只会备份当前数据库,备份文件名默认为 dump.rdb,可通过配置文件修改备份文件名 dbfilename xxx.rdb。可以通过以下命令查看备份文件目录和 RDB 文件名称:
$ redis-cli -h 127.0.0.1 -p 6379 127.0.0.1:6379> CONFIG GET dir 1) "dir" 2) "/usr/local/var/db/redis" 127.0.0.1:6379> CONFIG GET dbfilename 1) "dbfilename" 2) "dump.rdb"
RDB 文件的存储路径既可以在启动前配置,也可以通过命令动态设定。
config set dir {newdir} config set dbfilename {newFileName}
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对小牛知识库的支持。
本文向大家介绍一篇文章揭开Kotlin协程的神秘面纱,包括了一篇文章揭开Kotlin协程的神秘面纱的使用技巧和注意事项,需要的朋友参考一下 前言 Kotlin协程提供了一种新的异步执行方式,但直接查看库函数可能会有点混乱,本文中尝试揭开协程的神秘面纱。 理论 它是什么 这是别人翻译: 协程把异步编程放入库中来简化这类操作。程序逻辑在协程中顺序表述,而底层的库会将其转换为异步操作。库会将相关的用户代
主要内容:1 数据持久化,2 RDB(Redis DataBase)快照,2.1 RDB的原理,2.1 RDB的优缺点,2 AOF(append-only file)追加,2.1 AOF的原理,2.2 AOF重写,2.3 AOF的优缺点,3 混合持久化策略详细介绍了Redis的持久化机制,包括RDB与AOF持久化,以及混合持久化。 1 数据持久化 为了重启机器、机器故障、系统故障之后恢复数据,将内存中的数据写入到硬盘里面,这就是持久化,Redis恰好支持数据的持久化,这也是相比于Memcache
Redis 支持持久化,即把数据存储到硬盘中。 Redis 提供了两种持久化方式: RDB 快照(snapshot) - 将存在于某一时刻的所有数据都写入到硬盘中。 只追加文件(append-only file,AOF) - 它会在执行写命令时,将被执行的写命令复制到硬盘中。 这两种持久化方式既可以同时使用,也可以单独使用。 将内存中的数据存储到硬盘的一个主要原因是为了在之后重用数据,或者是为了防
主要内容:开启AOF持久化,AOF持久化机制,AOF策略配置,AOF和RDB对比AOF 被称为追加模式,或日志模式,是 Redis 提供的另一种持久化策略,它能够存储 Redis 服务器已经执行过的的命令,并且只记录对内存有过修改的命令,这种数据记录方法,被叫做“增量复制”,其默认存储文件为 。 开启AOF持久化 AOF 机制默认处于未开启状态,可以通过修改 Redis 配置文件开启 AOF,如下所示: 1) Windows系统 执行如下操作: 2) Linux系统 执行如下
主要内容:RDB快照模式原理,RDB持久化触发策略,RDB持久化优劣势Redis 是一款基于内存的非关系型数据库,它会将数据全部存储在内存中。但是如果 Redis 服务器出现某些意外情况,比如宕机或者断电等,那么内存中的数据就会全部丢失。因此必须有一种机制能够保证 Redis 储存的数据不会因故障而丢失,这就是 Redis 的数据持久化机制。 数据的持久化存储是 Redis 的重要特性之一,它能够将内存中的数据保存到本地磁盘中,实现对数据的持久存储。这样即使在服务器
本文向大家介绍redis持久化的介绍,包括了redis持久化的介绍的使用技巧和注意事项,需要的朋友参考一下 1. RDB 1.1 RDB简介 RDB:在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的Snapshot快照,它恢复时是将快照文件直接读到内存里。 工作机制:每隔一段时间,就把内存中的数据保存到硬盘上的指定文件中。 RDB是默认开启的! Redis会单独创建(fork)一个子