前言
Redis 是內(nèi)存數(shù)據(jù)庫(kù),數(shù)據(jù)都是存儲(chǔ)在內(nèi)存中,為了避免進(jìn)程退出導(dǎo)致數(shù)據(jù)的永久丟失,需要定期將 Redis 中的數(shù)據(jù)以數(shù)據(jù)或命令的形式從內(nèi)存保存到本地磁盤。當(dāng)下次 Redis 重啟時(shí),利用持久化文件進(jìn)行數(shù)據(jù)恢復(fù)。Redis 提供了 RDB 和 AOF 兩種持久化機(jī)制,前者將當(dāng)前的數(shù)據(jù)保存到磁盤,后者則是將每次執(zhí)行的寫(xiě)命令保存到磁盤(類似于 MySQL 的 Binlog)。本文將詳細(xì)介紹 RDB 和 AOF 兩種持久化方案,包括操作方法和持久化的實(shí)現(xiàn)原理。
正文
Redis 是一個(gè)基于 K-V 存儲(chǔ)的數(shù)據(jù)庫(kù)服務(wù)器,下面先介紹 Redis 數(shù)據(jù)庫(kù)的內(nèi)部構(gòu)造以及 K-V 的存儲(chǔ)形式,有助于我們更容易理解 Redis 的持久化機(jī)制。
1. Redis數(shù)據(jù)庫(kù)結(jié)構(gòu)
一個(gè)單機(jī)的 Redis 服務(wù)器默認(rèn)情況下有 16 個(gè)數(shù)據(jù)庫(kù)(0-15號(hào)),默認(rèn)使用的是 0 號(hào)數(shù)據(jù)庫(kù),可以使用 SELECT 命令切換數(shù)據(jù)庫(kù)。
Redis 中的每個(gè)數(shù)據(jù)庫(kù)都由一個(gè) redis.h/redisDb 結(jié)構(gòu)表示,它記錄了單個(gè) Redis 數(shù)據(jù)庫(kù)的鍵空間、所有鍵的過(guò)期時(shí)間、處于阻塞狀態(tài)和就緒狀態(tài)的鍵、數(shù)據(jù)庫(kù)編號(hào)等等。
typedef struct redisDb { // 數(shù)據(jù)庫(kù)鍵空間,保存著數(shù)據(jù)庫(kù)中的所有鍵值對(duì) dict *dict; // 鍵的過(guò)期時(shí)間,字典的鍵為鍵,字典的值為過(guò)期事件 UNIX 時(shí)間戳 dict *expires; // 正處于阻塞狀態(tài)的鍵 dict *blocking_keys; // 可以解除阻塞的鍵 dict *ready_keys; // 正在被 WATCH 命令監(jiān)視的鍵 dict *watched_keys; struct evictionPoolEntry *eviction_pool; // 數(shù)據(jù)庫(kù)編號(hào) int id; // 數(shù)據(jù)庫(kù)的鍵的平均 TTL,統(tǒng)計(jì)信息 long long avg_ttl;} redisDb;
由于 Redis 是一個(gè)鍵值對(duì)數(shù)據(jù)庫(kù)(key-value pairs database), 所以它的數(shù)據(jù)庫(kù)本身也是一個(gè)字典,對(duì)應(yīng)的結(jié)構(gòu)正是 redisDb。其中,dict 指向的是一個(gè)記錄鍵值對(duì)數(shù)據(jù)的字典,它的鍵是一個(gè)字符串對(duì)象,它的值則可以是字符串、列表、哈希表、集合和有序集合在內(nèi)的任意一種 Redis 類型對(duì)象。 expires 指向的是一個(gè)用于記錄鍵的過(guò)期時(shí)間的字典,它的鍵為 dict 中的數(shù)據(jù)庫(kù)鍵,它的值為這個(gè)數(shù)據(jù)庫(kù)鍵的過(guò)期時(shí)間戳,這個(gè)值以 long long 類型表示。
2. RDB持久化
RDB 持久化(也稱作快照持久化)是指將內(nèi)存中的數(shù)據(jù)生成快照保存到磁盤里面,保存的文件后綴是 .rdb。rdb 文件是一個(gè)經(jīng)過(guò)壓縮的二進(jìn)制文件,當(dāng) Redis 重新啟動(dòng)時(shí),可以讀取 rdb 快照文件恢復(fù)數(shù)據(jù)。RDB 功能最核心的是 rdbSave 和 rdbLoad 兩個(gè)函數(shù), 前者用于生成 RDB 文件并保存到磁盤,而后者則用于將 RDB 文件中的數(shù)據(jù)重新載入到內(nèi)存中:
RDB 文件是一個(gè)單文件的全量數(shù)據(jù),很適合數(shù)據(jù)的容災(zāi)備份與恢復(fù),通過(guò) RDB 文件恢復(fù)數(shù)據(jù)庫(kù)耗時(shí)較短,通常 1G 的快照文件載入內(nèi)存只需 20s 左右。Redis 提供了手動(dòng)觸發(fā)保存、自動(dòng)保存間隔兩種 RDB 文件的生成方式,下面先介紹 RDB 的創(chuàng)建和載入過(guò)程。
2.1. RDB的創(chuàng)建和載入
2.1.1. 手動(dòng)觸發(fā)保存
Redis 提供了兩個(gè)用于生成 RDB 文件的命令,一個(gè)是 SAVE,另一個(gè)是 BGSAVE。而觸發(fā) Redis 進(jìn)行 RDB 備份的方式有兩種,一種是通過(guò) SAVE 命令、BGSAVE 命令手動(dòng)觸發(fā)快照生成的方式,另一種是配置保存時(shí)間和寫(xiě)入次數(shù),由 Redis 根據(jù)條件自動(dòng)觸發(fā)保存操作。
1. SAVE命令
SAVE 是一個(gè)同步式的命令,它會(huì)阻塞 Redis 服務(wù)器進(jìn)程,直到 RDB 文件創(chuàng)建完成為止。在服務(wù)器進(jìn)程阻塞期間,服務(wù)器不能處理任何其他命令請(qǐng)求。
客戶端命令
127.0.0.1:6379> SAVEOK
服務(wù)端日志
6266:M 15 Sep 2019 08:31:01.258 * DB saved on disk
執(zhí)行 SAVE 命令后,Redis 在服務(wù)端進(jìn)程(PID為6266)執(zhí)行了 SAVE 操作,這個(gè)操作發(fā)生期間會(huì)一直阻塞 Redis 客戶端的請(qǐng)求處理。
2. BGSAVE命令
BGSAVE 是一個(gè)異步式的命令,和 SAVE 命令直接阻塞服務(wù)器進(jìn)程的做法不同,BGSAVE 命令會(huì)派生出一個(gè)子進(jìn)程,由子進(jìn)程負(fù)責(zé)創(chuàng)建 RDB 文件,服務(wù)器進(jìn)程(父進(jìn)程)繼續(xù)處理客戶的命令。
客戶端命令
127.0.0.1:6379> BGSAVEBackground saving started
服務(wù)端日志
6266:M 15 Sep 2019 08:31:22.914 * Background saving started by pid 62836283:C 15 Sep 2019 08:31:22.915 * DB saved on disk6266:M 15 Sep 2019 08:31:22.934 * Background saving terminated with success
通過(guò)服務(wù)端輸出的日志,可以發(fā)現(xiàn)Redis 在服務(wù)端進(jìn)程(PID為6266)會(huì)為 BGSAVE 命令單獨(dú)創(chuàng)建(fork)一個(gè)子進(jìn)程(PID為6283),并由子進(jìn)程在后臺(tái)完成 RDB 的保存過(guò)程,在操作完成之后通知父進(jìn)程然后退出。在整個(gè)過(guò)程中,服務(wù)器進(jìn)程只會(huì)消耗少量時(shí)間在創(chuàng)建子進(jìn)程和處理子進(jìn)程信號(hào)量上面,其余時(shí)間都是待命狀態(tài)。
BGSAVE 是觸發(fā) RDB 持久化的主流方式,下面給出 BGSAVE 命令生成快照的流程:
3. SAVE和BGSAVE的比較
命令 | SAVE | BGSAVE |
---|---|---|
IO類型 | 同步 | 異步 |
是否阻塞 | 全程阻塞 | fork時(shí)發(fā)生阻塞 |
復(fù)雜度 | O(n) | O(n) |
優(yōu)點(diǎn) | 不會(huì)消耗額外的內(nèi)存 | 不阻塞客戶端 |
缺點(diǎn) | 阻塞客戶端 | fork子進(jìn)程消耗內(nèi)存 |
2.1.2. 自動(dòng)觸發(fā)保存
因?yàn)?BGSAVE 命令可以在不阻塞服務(wù)器進(jìn)程的情況下執(zhí)行,所以 Redis 的配置文件 redis.conf 提供了一個(gè) save 選項(xiàng),讓服務(wù)器每隔一段時(shí)間自動(dòng)執(zhí)行一次 BGSAVE 命令。用戶可以通過(guò) save 選項(xiàng)設(shè)置多個(gè)保存條件,只要其中任意一個(gè)條件被滿足,服務(wù)器就會(huì)執(zhí)行 BGSAVE 命令。 Redis 配置文件 redis.conf 默認(rèn)配置了以下 3 個(gè)保存條件:
save 900 1save 300 10 save 60 10000
那么只要滿足以下 3 個(gè)條件中的任意一個(gè),BGSAVE 命令就會(huì)被自動(dòng)執(zhí)行:
Redis 服務(wù)器會(huì)周期性地操作 serverCron 函數(shù),這個(gè)函數(shù)每隔 100 毫秒就會(huì)執(zhí)行一次,它的一項(xiàng)任務(wù)就是檢查 save 選項(xiàng)所設(shè)置的保存條件是否滿足,如果滿足的話,就自動(dòng)執(zhí)行 BGSAVE 命令。
2.1.3. 啟動(dòng)自動(dòng)載入
和使用 SAVE 和 BGSAVE 命令創(chuàng)建 RDB 文件不同,Redis 沒(méi)有專門提供用于載入 RDB 文件的命令,RDB 文件的載入過(guò)程是在 Redis 服務(wù)器啟動(dòng)時(shí)自動(dòng)完成的。啟動(dòng)時(shí)只要在指定目錄檢測(cè)到 RDB 文件的存在,Redis 就會(huì)通過(guò) rdbLoad 函數(shù)自動(dòng)載入 RDB 文件。
下面是 Redis 服務(wù)器啟動(dòng)時(shí)打印的日志,倒數(shù)第 2 條日志是在成功載入 RDB 文件后打印的。
$ redis-server /usr/local/etc/redis.conf6266:C 15 Sep 2019 08:30:41.830 # Redis version=5.0.5, bits=64, commit=00000000, modified=0, pid=6266, just started6266:C 15 Sep 2019 08:30:41.830 # Configuration loaded6266: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 initialized6266:M 15 Sep 2019 08:30:41.833 * DB loaded from disk: 0.001 seconds6266:M 15 Sep 2019 08:30:41.833 * Ready to accept connections
由于 AOF 文件屬于增量的寫(xiě)入命令備份,RDB 文件屬于全量的數(shù)據(jù)備份,所以更新頻率比 RDB 文件的更新頻率高。所以如果 Redis 服務(wù)器開(kāi)啟了 AOF 持久化功能,那么服務(wù)器會(huì)優(yōu)先使用 AOF 文件來(lái)還原數(shù)據(jù)庫(kù)狀態(tài);只有在 AOF 的持久化功能處于關(guān)閉狀態(tài)時(shí),服務(wù)器才會(huì)使用優(yōu)先使用 RDB 文件還原數(shù)據(jù)庫(kù)狀態(tài)。
2.2. RDB的文件結(jié)構(gòu)
RDB 文件是經(jīng)過(guò)壓縮的二進(jìn)制文件,下面介紹關(guān)于RDB文件的一些細(xì)節(jié)。
2.2.1. 存儲(chǔ)路徑
SAVE 命令和 BGSAVE 命令都只會(huì)備份當(dāng)前數(shù)據(jù)庫(kù),備份文件名默認(rèn)為 dump.rdb,可通過(guò)配置文件修改備份文件名 dbfilename xxx.rdb。可以通過(guò)以下命令查看備份文件目錄和 RDB 文件名稱:
$ redis-cli -h 127.0.0.1 -p 6379127.0.0.1:6379> CONFIG GET dir1) "dir"2) "/usr/local/var/db/redis"127.0.0.1:6379> CONFIG GET dbfilename1) "dbfilename"2) "dump.rdb"
RDB 文件的存儲(chǔ)路徑既可以在啟動(dòng)前配置,也可以通過(guò)命令動(dòng)態(tài)設(shè)定。
config set dir {newdir}config set dbfilename {newFileName}
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)武林網(wǎng)的支持。
新聞熱點(diǎn)
疑難解答
圖片精選