前言redis
Redis 是內存數據庫,數據都是存儲在內存中,爲了不進程退出致使數據的永久丟失,須要按期將 Redis 中的數據以數據或命令的形式從內存保存到本地磁盤。當下次 Redis 重啓時,利用持久化文件進行數據恢復。Redis 提供了 RDB 和 AOF 兩種持久化機制,前者將當前的數據保存到磁盤,後者則是將每次執行的寫命令保存到磁盤(相似於 MySQL 的 Binlog)。本文將詳細介紹 RDB 和 AOF 兩種持久化方案,包括操做方法和持久化的實現原理。數據庫
Redis 是一個基於鍵值對(K-V)存儲的數據庫服務器,下面先介紹 Redis 數據庫的內部構造以及 K-V 的存儲形式,有助於咱們更容易理解 Redis 的持久化機制。緩存
一個單機的 Redis 服務器默認狀況下有 16 個數據庫(0-15 號),數據庫的個數是可配置的。Redis 默認使用的是 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 類型表示。架構
RDB 持久化(也稱做快照持久化)是指將內存中的數據生成快照保存到磁盤裏面,保存的文件後綴是 .rdb。rdb 文件是一個通過壓縮的二進制文件,當 Redis 從新啓動時,能夠讀取 rdb 快照文件恢復數據。RDB 功能最核心的是 rdbSave 和 rdbLoad 兩個函數, 前者用於生成 RDB 文件並保存到磁盤,然後者則用於將 RDB 文件中的數據從新載入到內存中:app
RDB 文件是一個單文件的全量數據,很適合數據的容災備份與恢復,經過 RDB 文件恢復數據庫耗時較短,一般 1G 的快照文件載入內存只需 20s 左右。Redis 提供了手動觸發保存、自動保存間隔兩種 RDB 文件的生成方式,下面先介紹 RDB 的建立和載入過程。異步
Redis 服務器默認是經過 RDB 方式完成持久化的,對應 redis.conf 文件的配置項以下:分佈式
# RDB文件的名稱 dbfilename dump.rdb # 備份RDB和AOF文件存放路徑 dir /usr/local/var/db/redis/
Redis 提供了兩個用於生成 RDB 文件的命令,一個是 SAVE,另外一個是 BGSAVE。而觸發 Redis 進行 RDB 備份的方式有兩種,一種是經過 SAVE 命令、BGSAVE 命令手動觸發快照生成的方式,另外一種是配置保存時間和寫入次數,由 Redis 根據條件自動觸發保存操做。函數
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 客戶端的請求處理。
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 命令生成快照的流程:
命令 | SAVE | BGSAVE |
---|---|---|
IO 類型 | 同步 | 異步 |
是否阻塞 | 全程阻塞 | fork 時發生阻塞 |
複雜度 | O(n) | O(n) |
優勢 | 不會消耗額外的內存 | 不阻塞客戶端 |
缺點 | 阻塞客戶端 | fork 子進程消耗內存 |
由於 BGSAVE 命令能夠在不阻塞服務器進程的狀況下執行,因此 Redis 的配置文件 redis.conf 提供了一個 save 選項,讓服務器每隔一段時間自動執行一次 BGSAVE 命令。用戶能夠經過 save 選項設置多個保存條件,只要其中任意一個條件被知足,服務器就會執行 BGSAVE 命令。Redis 配置文件 redis.conf 默認配置瞭如下 3 個保存條件:
save 900 1 save 300 10 save 60 10000
那麼只要知足如下 3 個條件中的任意一個,BGSAVE 命令就會被自動執行:
好比經過命令 SET msg "hello" 插入一條鍵值對,等待 900 秒後 Reids 服務器進程自動觸發保存,輸出以下:
6266:M 15 Sep 2019 08:46:22.981 * 1 changes in 900 seconds. Saving... 6266:M 15 Sep 2019 08:46:22.986 * Background saving started by pid 6266 6476:C 15 Sep 2019 08:46:23.015 * DB saved on disk 6266:M 15 Sep 2019 08:46:23.096 * Background saving terminated with success
Redis 服務器會週期性地操做 serverCron 函數,這個函數每隔 100 毫秒就會執行一次,它的一項任務就是檢查 save 選項所設置的保存條件是否知足,若是知足的話,就自動執行 BGSAVE 命令。
和使用 SAVE 和 BGSAVE 命令建立 RDB 文件不一樣,Redis 沒有專門提供用於載入 RDB 文件的命令,RDB 文件的載入過程是在 Redis 服務器啓動時自動完成的。啓動時只要在指定目錄檢測到 RDB 文件的存在,Redis 就會經過 rdbLoad 函數自動載入 RDB 文件。
下面是 Redis 服務器啓動時打印的日誌,倒數第 2 條日誌是在成功載入 RDB 文件後打印的。
$ redis-server /usr/local/etc/redis.conf 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 文件還原數據庫狀態。
RDB 文件是通過壓縮的二進制文件,下面介紹關於 RDB 文件內部構造的一些細節。
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
RDB 文件有固定的格式要求,它保存的是二進制數據,大致能夠分爲如下 5 部分:
REDIS:文件頭保存的是長爲 5 個字節的 REDIS 字符,用於標識當前文件爲 RDB 類型
db_version:一個 4 個字節長的整數字符串,用於記錄 RDB 文件的版本號
aux:記錄着 RDB 文件中元數據信息,包含 8 個附加
databases:部分包含着零個或者任意多個數據庫,以及各個數據庫的鍵值對數據
EOF:是 1 個字節的常量,用於標誌 RDB 文件的正文內容結束
check_sum:一個 8 字節長的整數,保存着由前面四個部分計算獲得的校驗和,用於檢測 RDB 文件的完整性
一個 RDB 文件的 databases 部分包含着零個或者任意多個數據庫(database),而每一個非空的 database 都包含 SELECTDB、db_number 以及 key_value_pairs 三個部分:
RDB 的 key_value_pairs 部分保存了一個或者多個鍵值對,若是鍵值對有過時時間,過時時間會被保存在鍵值對的前面。下面是這兩種鍵值對的內部結構:
EXPIREMENT_MS:長度爲一個字節的常量,告訴用戶程序接下來要讀取的是一個以毫秒爲單位的過時時間
ms:一個長度爲 8 個字節的整數,記錄着鍵值對的過時時間,是一個以毫秒爲單位的時間戳
TYPE:記錄了 value 的類型,長度爲 1 個字節。每一個 TYPE 常量都表明了一種對象類型或者底層編碼, 當服務器讀入 RDB 文件中的鍵值對數據時, 程序會根據 TYPE 的值來決定如何讀入和解釋 value 的數據。它的值定義一般爲如下常量之一:
key:一個字符串對象,編碼格式和 REDIS_RDB_TYPE_STRING 類型的 value 同樣
value:取決於 TYPE 的類型,對象類型能夠是 string、list、set、zset 和 hash
爲了查看 RDB 文件內部的結構,執行如下命令往 Redis 服務器插入 3 條鍵值對數據:
127.0.0.1:6379> SADD fruits "apple" "banana" "orange" (integer) 3 127.0.0.1:6379> LPUSH numbers 128 256 512 (integer) 3 127.0.0.1:6379> SET msg "hello" OK
執行 SAVE 操做,將 Redis 進程中的數據強制持久化到 dump.rdb 文件中
127.0.0.1:6379> SAVE OK
經過 Linux 的 od 命令將二進制文件 dump.rdb 中的數據轉換爲 ASCII 格式輸出,跟前面提到的存儲格式大體是同樣的:
$ od -c dump.rdb 0000000 R E D I S 0 0 0 9 372 \t r e d i s 0000020 - v e r 005 5 . 0 . 5 372 \n r e d i 0000040 s - b i t s 300 @ 372 005 c t i m e 200 0000060 200 200 231 ] 372 \b u s e d - m e m 302 200 0000100 \v 020 \0 372 \f a o f - p r e a m b l 0000120 e 300 \0 376 \0 373 003 \0 \0 003 m s g 005 h e 0000140 l l o 016 \a n u m b e r s 001 027 027 \0 0000160 \0 \0 022 \0 \0 \0 003 \0 \0 300 \0 002 004 300 \0 001 0000200 004 300 200 \0 377 002 006 f r u i t s 003 006 o 0000220 r a n g e 005 a p p l e 006 b a n a 0000240 n a 377 214 ک ** 3 366 < r X 0000253
下面是 redis.conf 文件中和 RDB 文件相關的經常使用配置項(以及默認值):
RDB 持久化是按期把內存中的數據全量寫入到文件中,除此以外,RDB 還提供了基於 AOF(Append Only File)的持久化功能。AOF 會把 Redis 服務器每次執行的寫命令記錄到一個日誌文件中,當服務器重啓時再次執行 AOF 文件中的命令來恢復數據。
AOF 的主要做用是解決了數據持久化的實時性,目前已經成爲了 Redis 持久化的主流方式。
默認狀況下 AOF 功能是關閉的,Redis 只會經過 RDB 完成數據持久化的。開啓 AOF 功能須要 redis.conf 文件中將 appendonly 配置項修改成 yes,這樣在開啓 AOF 持久化功能的同時,將基於 RDB 的快照持久化置於低優先級。修改 redis.conf 以下:
# 此選項爲AOF功能的開關,默認爲no,經過yes來開啓aof功能 appendonly yes # 指定AOF文件名稱 appendfilename appendonly.aof # 備份RDB和AOF文件存放路徑 dir /usr/local/var/db/redis/
重啓 Redis 服務器進程之後,dir 目錄下會生成一個 appendonly.aof 文件,因爲此時服務器未執行任何寫指令,所以 AOF 文件是空的。執行如下命令寫入幾條測試數據:
127.0.0.1:6379> SADD fruits "apple" "banana" "orange" (integer) 3 127.0.0.1:6379> LPUSH numbers 128 256 512 (integer) 3 127.0.0.1:6379> SET msg "hello" OK
AOF 文件是純文本格式的,上述寫命令按順序被寫入了 appendonly.aof 文件(省掉換行符 '\r\n'):
/usr/local/var/db/redis$ cat appendonly.aof *2 $6 SELECT $1 0 *5 $4 SADD $6 fruits $5 apple $6 banana $6 orange *5 $5 LPUSH $7 numbers $3 128 $3 256 $3 512 *3 $3 SET $3 msg $5 hello
RDB 持久化的方式是將 apple、banana、orange 的鍵值對數據保存爲 RDB 的二進制文件,而 AOF 是經過把 Redis 服務器執行的 SADD、LPUSH、SET 等命令保存到 AOF 的文本文件中。下圖是 AOF 文件內部的構造圖:
再次重啓 Redis 服務器進程,觀察啓動日誌會發現 Redis 會經過 AOF 文件加載數據:
52580:M 15 Sep 2019 16:09:47.015 # Server initialized 52580:M 15 Sep 2019 16:09:47.015 * DB loaded from append only file: 0.001 seconds 52580:M 15 Sep 2019 16:09:47.015 * Ready to accept connections
經過命令讀取 AOF 文件還原的鍵值對數據:
127.0.0.1:6379> SMEMBERS fruits 1) "apple" 2) "orange" 3) "banana" 127.0.0.1:6379> LRANGE numbers 0 -1 1) "512" 2) "256" 3) "128" 127.0.0.1:6379> GET msg "hello"
AOF 不須要設置任何觸發條件,對 Redis 服務器的全部寫命令都會自動記錄到 AOF 文件中,下面介紹 AOF 持久化的執行流程。
AOF 文件的寫入流程能夠分爲如下 3 個步驟:
Redis 使用單線程處理客戶端命令,爲了不每次有寫命令就直接寫入磁盤,致使磁盤 IO 成爲 Redis 的性能瓶頸,Redis 會先把執行的寫命令追加(append)到一個 aof_buf 緩衝區,而不是直接寫入文件。
命令追加的格式是 Redis 命令請求的協議格式,它是一種純文本格式,具備兼容性好、可讀性強、容易處理、操做簡單避免二次開銷等優勢。在 AOF 文件中,除了用於指定數據庫的 select 命令(好比:select 0 爲選中 0 號數據庫)是由 Redis 添加的,其餘都是客戶端發送來的寫命令。
Redis 提供了多種 AOF 緩存區的文件同步策略,相關策略涉及到操做系統的 write() 函數和 fsync() 函數,說明以下:
爲了提升文件的寫入效率,當用戶調用 write 函數將數據寫入文件時,操做系統會先把數據寫入到一個內存緩衝區裏,當緩衝區被填滿或超過了指定時限後,才真正將緩衝區的數據寫入到磁盤裏。
雖然操做系統底層對 write() 函數進行了優化 ,但也帶來了安全問題。若是宕機內存緩衝區中的數據會丟失,所以系統同時提供了同步函數 fsync() ,強制操做系統馬上將緩衝區中的數據寫入到磁盤中,從而保證了數據持久化。
Redis 提供了 appendfsync 配置項來控制 AOF 緩存區的文件同步策略,appendfsync 可配置如下三種策略:
命令寫入 aof_buf 緩衝區後當即調用系統 fsync 函數同步到 AOF 文件,fsync 操做完成後線程返回,整個過程是阻塞的。這種狀況下,每次有寫命令都要同步到 AOF 文件,硬盤 IO 成爲性能瓶頸,Redis 只能支持大約幾百 TPS 寫入,嚴重下降了 Redis 的性能。
命令寫入 aof_buf 緩衝區後調用系統 write 操做,不對 AOF 文件作 fsync 同步;同步由操做系統負責,一般同步週期爲 30 秒。這種狀況下,文件同步的時間不可控,且緩衝區中堆積的數據會不少,數據安全性沒法保證。
命令寫入 aof_buf 緩衝區後調用系統 write 操做,write 完成後線程馬上返回,fsync 同步文件操做由單獨的進程每秒調用一次。everysec 是前述兩種策略的折中,是性能和數據安全性的平衡,所以也是 Redis 的默認配置,也是比較推崇的配置選項。
文件同步策略 | write 阻塞 | fsync 阻塞 | 宕機時的數據丟失量 |
---|---|---|---|
always | 阻塞 | 阻塞 | 最多隻丟失一個命令的數據 |
no | 阻塞 | 不阻塞 | 操做系統最後一次對 AOF 文件 fsync 後的數據 |
everysec | 阻塞 | 不阻塞 | 通常不超過 1 秒鐘的數據 |
隨着命令不斷寫入 AOF,文件會愈來愈大,致使文件佔用空間變大,數據恢復時間變長。爲了解決這個問題,Redis 引入了重寫機制來對 AOF 文件中的寫命令進行合併,進一步壓縮文件體積。
AOF 文件重寫指的是把 Redis 進程內的數據轉化爲寫命令,同步到新的 AOF 文件中,而後使用新的 AOF 文件覆蓋舊的 AOF 文件,這個過程不對舊的 AOF 文件的進行任何讀寫操做。
AOF 重寫過程提供了手動觸發和自動觸發兩種機制:
手動觸發:直接調用 bgrewriteaof 命令,該命令的執行與 bgsave 有些相似,都是 fork 子進程進行具體的工做,且都只有在 fork 時會阻塞
自動觸發:根據 auto-aof-rewrite-min-size 和 auto-aof-rewrite-percentage 配置項,以及 aof_current_size 和 aof_base_size 的狀態肯定觸發時機
下面以手動觸發 AOF 重寫爲例,當 bgrewriteaof 命令被執行時,AOF 文件重寫的流程以下:
客戶端經過 bgrewriteaof 命令對 Redis 主進程發起 AOF 重寫請求
當前不存在正在執行 bgsave/bgrewriteaof 的子進程時,Redis 主進程經過 fork 操做建立子進程,這個過程主進程是阻塞的。若是發現 bgrewriteaof 子進程直接返回;若是發現 bgsave 子進程則等 bgsave 執行完成後再執行 fork 操做
主進程的 fork 操做完成後,繼續處理其餘命令,把新的寫命令同時追加到 aof_buf 和 aof_rewrite_buf 緩衝區中
子進程讀取 Redis 進程中的數據快照,生成寫入命令並按照命令合併規則批量寫入到新的 AOF 文件
子進程寫完新的 AOF 文件後,向主進程發信號,主進程更新統計信息,具體能夠經過 info persistence 查看
主進程接受到子進程的信號之後,將 aof_rewrite_buf 緩衝區中的寫命令追加到新的 AOF 文件
主進程使用新的 AOF 文件替換舊的 AOF 文件,AOF 重寫過程完成
文件重寫之因此可以壓縮 AOF 文件的大小,緣由在於如下幾方面:
下面是 redis.conf 文件中和 AOF 文件相關的經常使用配置項(以及默認值):
前面提到當 AOF 持久化功能開啓時,Redis 服務器啓動時優先執行 AOF 文件的命令恢復數據,只有當 AOF 功能關閉時,纔會優先載入 RDB 快照的文件數據。
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
9447:M 15 Sep 2019 23:01:46.601 # Server initialized 9447:M 15 Sep 2019 23:01:46.602 * DB loaded from append only file: 0.001 seconds 9447:M 15 Sep 2019 23:01:46.602 * Ready to accept connections
9326:M 15 Sep 2019 22:49:24.203 # Server initialized 9326:M 15 Sep 2019 22:49:24.203 * Ready to accept connections
持久化機制 | RDB | AOF |
---|---|---|
啓動優先級 | 低 | 高 |
磁盤文件體積 | 小 | 大 |
數據還原速度 | 快 | 慢 |
數據安全性 | 容易丟失數據 | 根據策略決定 |
操做輕重級別 | 重 | 輕 |
在重啓 Redis 服務器時,通常不多使用 RDB 快照文件來恢復內存狀態,由於會丟失大量數據。更多的是使用 AOF 文件進行命令重放,可是執行 AOF 命令性能相對 RDB 來講要慢不少。這樣在 Redis 數據很大的狀況下,啓動須要消耗大量的時間。
鑑於 RDB 快照可能會形成數據丟失,AOF 指令恢復數據慢,Redis 4.0 版本提供了一套基於 AOF-RDB 的混合持久化機制,保留了兩種持久化機制的優勢。這樣重寫的 AOF 文件由兩部份組成,一部分是 RDB 格式的頭部數據,另外一部分是 AOF 格式的尾部指令。
Redis 4.0 版本的混合持久化功能默認是關閉的,經過配置 aof-use-rdb-preamble 爲 yes 開啓此功能:
# 開啓AOF-RDB混合持久化機制 aof-use-rdb-preamble yes
查看 Redis 服務器是否開啓混合持久化功能:
127.0.0.1:6379> CONFIG GET aof-use-rdb-preamble 1) "aof-use-rdb-preamble" 2) "yes"
如圖所示,將 RDB 數據文件的內容和增量的 AOF 命令文件存在一塊兒。這裏的 AOF 命令再也不是全量的命令,而是自持久化開始到持久化結束的這段時間服務器進程執行的增量 AOF 命令,一般這部分 AOF 命令很小。
在 Redis 服務器重啓的時候,能夠預先加載 AOF 文件頭部全量的 RDB 數據,而後再重放 AOF 文件尾部增量的 AOF 命令,從而大大減小了重啓過程當中數據還原的時間。
在介紹持久化策略以前,首先要明白不管是 RDB 仍是 AOF 方式,開啓持久化都是會形成性能開銷的。
RDB 持久化:
AOF 持久化:
相對來講,因爲 AOF 向磁盤中寫入數據的頻率更高,所以對 Redis 服務器主進程性能的影響會更大。
在實際生產環境中,根據數據量、應用對數據的安全要求、預算限制等不一樣狀況,會有各類各樣的持久化策略。
對於分佈式環境,持久化的選擇必須與 Redis 的主從策略一塊兒考慮,由於主從複製與持久化一樣具備數據備份的功能,並且主節點(Master Node)和從節點(Slave Node)能夠獨立選擇持久化方案。
下面分場景來討論持久化策略的選擇,下面的討論也只是做爲參考,實際方案可能更復雜更具多樣性。
若是 Redis 中的數據徹底丟棄也沒有關係(如 Redis 徹底用做 DB 層數據的緩存),那麼不管是單機,仍是主從架構,均可以不進行任何持久化。
在單機環境下,若是能夠接受十幾分鍾或更多的數據丟失,RDB 方案對 Redis 的性能更加有利;若是隻能接受秒級別的數據丟失,選擇 AOF 方案更合適。
在多數狀況下,Redis 都會配置主從部署機制。從節點(slave)既能夠實現數據的熱備,也能夠進行讀寫分擔 Redis 讀請求,以及在主節點(master)宕機後的頂替做用。
在這種狀況下,一種可行的作法以下:
爲何開啓了主從複製,能夠實現數據的熱備份,還須要設置持久化呢?由於在一些特殊狀況下,主從複製仍然不足以保證數據的安全,例如:
master 和 slave 同時中止:若是 master 節點和 slave 節點位於同一個機房,則一次停電事故就可能致使 master 和 slave 機器同時關機,Redis 服務器進程中止。若是沒有持久化,則面臨的是數據的徹底丟失。
master 重啓:若是 master 節點由於故障宕機,而且系統中有自動拉起機制(即檢測到服務中止後重啓該服務)將 master 節點自動重啓。
前面的幾種持久化策略,針對的都是通常的系統故障,如進程異常退出、宕機、斷電等,這些故障不會損壞硬盤。可是對於一些可能致使硬盤損壞的災難狀況,如火災地震,就須要進行異地災備。
因爲 RDB 文件文件小、恢復速度快,災難恢復通常採用 RDB 方式;異地備份的頻率根據數據安全性的須要及其它條件來肯定,但最好不要低於一天一次。
本文主要開篇介紹了 Redis 服務器的數據庫結構,進一步介紹了 Redis 提供的幾種持久化機制,包括基於數據快照的 RDB 全量持久化、基於命令追加的 AOF 增量持久化以及 Redis 4.0 支持的混合持久化。對於 RDB 的持久化方式,給出了 RDB 快照的建立和還原過程,RDB 的文件結構以及相關配置項。對於 AOF 的持久化方式,給出了 AOF 日誌的建立和還原過程,AOF 的執行流程,AOF 文件內部的格式以及相關配置項。在文章結尾分析了 RDB 和 AOF 方式各自的優缺點,性能開銷,以及在單機環境、主從部署、異地備災場景下的持久化策略。