面試官:說下 Redis 是如何保證在宕機後數據不丟失的 持久化 RDB 和 AOF RDB AOF 文件載入順序

持久化

首先我們說下什麼是持久化,持久化是將程序數據在持久狀態和瞬時狀態間轉換的機制。通俗的講,就是瞬時數據(比如內存中的數據,是不能永久保存的)持久化爲持久數據(比如持久化至數據庫中,能夠長久保存)。另外我們使用的 Redis 之所以快就是因爲數據都存儲在內存當中,爲了保證在服務器出現異常過後還能恢復數據,所以就有了 Redis 的持久化。

RDB 和 AOF

前面說了什麼是持久化,現在說說 Redis 的持久化,衆所周知 Redis 的持久化有兩種方式,一種是快照形式 RDB,另一種是增量文件 AOF。

RDB

RDB 持久化方式是會在一個特定的時間間隔裏面保存某個時間點的數據快照,我們拿到這個數據快照過後就可以根據這個快照完整的複製出數據。這種方式我們可以用來備份數據,把快照文件備份起來,傳送到其他服務器就可以直接恢復數據。但是這只是某個時間點的全部數據,如果我們想要最新的數據,就只能定期的去生成快照文件。

RDB 的實現主要是通過創建一個子進程來實現 RDB 文件的快照生成,通過子進程來實現備份功能,不會影響主進程的性能。同時上面也提到 RDB 的快照文件是保存一定時間間隔的數據的,這就會導致如果時間間隔過長,服務器出現異常還沒來得及生成快照的時候就會丟失這個間隔時間的所有數據;那有同學就會說,我們可以把時間間隔設置的短一點,適當的縮短是可以的,但是如果間隔時間段設置短一點頻繁的生成快照對系統還是會有影響的,特別是在數據量大的情況下,高性能的環境下是不允許這種情況出現的。

我們可以在 redis.conf 進行 RDB 的相關配置,配置生成快照的策略,以及日誌文件的路徑和名稱。還有定時備份規則,如下圖所示,裏面的註釋寫的很清楚,簡單說就是在多少時間以內多少個 key 變化了就會觸發快照。如save 300 10 表示在 5 分鐘內如果有 10 個 key 發生了變化就會觸發生產快照,其他的同理。

除了我們在配置文件中配置自動生成快照文件之外,Redis 本身提供了相關的命令可以讓我們手動生成快照文件,分別是 SAVEBGSAVE ,這兩個命令功能相同但是方式和效果不一樣,SAVE 命令執行完後阻塞服務器進程,阻塞過後服務器就不能處理任何請求,所以在生產上不能用,和SAVE 命令直接阻塞服務器進程的做法不同,BGSAVE 命令是生成一個子進程,通過子進程來創建 RDB 文件,主進程依舊可以處理接受到的命令,從而不會阻塞服務器,在生產上可以使用。

在這裏測試一下自動生成快照,我們修改一下快照的生成策略爲save 10 2,然後在本地啓動Redis 服務,並用 redis-cli 鏈接進入,依次步驟如下

  1. 修改配置,如下
  2. 啓動 Redis 服務,我們可以從啓動日誌中看到,默認是會先讀取 RDB 文件進行恢復的
  3. 鏈接 Redis 服務,並在 10s 內設置 3 個 key
  4. 這個時候我們會看到 Redis 的日誌裏面會輸出下面內容,因爲觸發了規則,所以開啓子進程進行數據備份,同時在對應的文件路徑下面,我們也看到了 rdb 文件。

從上面可以看出,我們配置的規則生效了,也成功的生成了 RDB 文件, 後續在服務器出現異常的情況,只要重新啓動就會讀取對應的 RDB 文件進行數據備份。

AOF

AOF 是一種追加執行命令的形式,它跟 RDB 的區別是,AOF 並不是把數據保存下來,而是保存執行的動作。在開啓 AOF 功能的時候,客戶端連接後執行的每一條命令都會被記錄下來。這其實讓阿粉想起來的 MySQL 的 binlog 日誌,也是記錄操作的命令,後續可以根據文件去恢復數據。

AOF 是追加命令格式的文件,同樣的我們可以定義多長時間把數據同步一次,Redis 本身提供了三種策略來實現命令的同步,分別是不進行同步,每秒同步一次,以及當有查詢的時候同步一次。默認的策略也是使用最多的策略就是每秒同步一次,這樣我們可以知道,丟失的數據最多也就只有一秒鐘的數據。有了這種機制,AOF 會比 RDB 可靠很多,但是因爲文件裏面存在的是執行的命令,所以AOF 的文件一般也會比 RDB 的文件大點。

Redis 的 AOF 功能,默認是沒有開啓的,我們可以通過在配置文件中配置appendonly yes是功能開啓,同時配置同步策略appendfsync everysec 開啓每秒鐘同步一次,我們拿到 AOF 文件過後,可以根據這個文件恢復數據。

同樣的我們在redis.conf 中可以看到默認是沒有開啓 AOF 功能的,並且我們也可以指定對應的文件名稱和路徑。

接下來,我們測試一下開啓 AOF 功能,先修改配置然後重啓 Redis 的服務器,我們會發現已經沒有讀取 RDB 文件的日誌了,並且在日誌文件路徑下面已經生成了一個 aof 文件。需要注意的是,因爲我們重啓的服務,並且開啓了 AOF,所以現在 Redis 服務器裏面並沒有我們之前添加的數據(說明什麼問題呢?)。

接下來我們使用客戶端連接進入,設置如下值,接下來我們可以看看 aof 文件裏面的內容

我們可以看到aof 文件裏面的內容就是執行的命令,只不過是以一種固定的格式存儲的,我們在備份的時候如果不需要哪些數據,可以手動刪掉對應的命令就可以重新備份數據。

文件載入順序

上面我們提到了Redis 的兩種持久化方案,並且兩種方案都會生成對應的文件,那 Redis 在恢復數據的時候是怎麼載入文件的呢?並且在兩個文件都存在的情況下,會以哪個爲準呢?

通過上面的測試,其實我們可以看出 Redis 是以 AOF 爲優先的,畢竟 AOF 相對 RDB 來說在出現異常的情況下保存的數據更加完整。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章