Redis(五)--- Redis的持久化RDB與AOF

MouseDong發表於2019-07-27

一、Redis資料庫

我們都知道Redis是基於記憶體的資料庫,資料是以key-value鍵值對的方式儲存的,那麼key-value鍵值對是隨意放在記憶體中的麼,其實Redis的服務會建立很多的資料庫空間,這些key-value鍵值對都是在各個資料庫空間中儲存的。

當我們使用客戶端工具連結Redis服務時,會在客戶端中看到一系列的db*命名的項(如圖),這些就是一個個資料庫,Redis初始化建立16個資料庫,資料庫建立個數可以在配置檔案中修改。

而在命令列模式中是看不到這些資料庫的具體數量的,但在命令列提示符的右側會提示我們當前處於哪個資料庫(如圖),並且可以用上一章說到的SELECT命令進行資料庫的切換;客戶端預設連線第一個資料庫,即0號資料庫。

(1)資料庫鍵空間

key-value鍵值對儲存在各個資料庫中,而每個資料庫內部都是由一個redisDb結構,結構中有若干個屬性,最主要的有兩個屬性dict、expires。

1 typedef struct redisDb {
2     // ...
3     // 資料庫鍵空間,儲存著資料庫中的所有鍵值對
4     dict *dict;
5 
6     // 過期字典,儲存著鍵的過期時間
7     dict *expires;
8     // ...
9 } redisDb;
    • dict 是字典結構,儲存我們的key-value鍵值對,這個字典稱為資料庫鍵空間,字典的鍵就是資料庫的鍵,每個鍵都是一個字串,儲存key值;字典的值就是資料庫的值,每個值都可以是五大物件中任意一種,儲存value值;所以我們儲存的key-value最終是在資料庫中以字典的結構儲存的。
    • expires 同樣是字典結構,但其儲存的是key-value過期時間;當我們設定了key-value的過期時間,那麼key-value儲存在dict字典中,而過期時間則儲存在expires中;字典的鍵儲存key,字典的值儲存過期時間;這裡需要注意的是,無論設定的過期時間是秒還是毫秒,最終儲存時都會轉換為unix毫秒時間戳。

圖中是帶有過期字典的資料庫例子

(2)持久化

上面說道的無論是資料庫還是期內的資料都是儲存在伺服器內記憶體中的,如果伺服器一旦發生掉電,程式退出等情況,那麼其記憶體中的資料就都消失不見了,在我們大規模併發的專案下,顯然這是災難性的,所以應對這種情況的辦法之一,就是持久化,把記憶體中的數放到磁碟中,意外發生後,能夠從磁碟上進行資料恢復到記憶體中,這樣就避免了資料丟失。

Redis提供了兩種持久化方式RDB持久化和AOF持久化。

2、RDB持久化

RDB持久化是最直接的持久化方式,直接將記憶體中的資料儲存到RDB檔案中,當恢復時也是直接從RDB檔案中恢復;

                      

 

    • RDB檔案是經過壓縮的二進位制檔案,這裡對檔案結構不做詳解。
    • RDB持久化可以手動執行,也可以設定定期執行。
    • RDB持久化命令有兩個SAVE(同步)和BGSAVE(非同步),同步持久化過程中,會拒絕客戶端的所有請求;非同步則是建立子程式執行,不會對客戶端產生影響,具體可以看上一章的命令介紹。

自動間隔性儲存

因為BGSAVE命令是非同步執行,不會阻塞伺服器,所以Redis允許使用者自行配置SAVE選項,當選項觸發時自動執行BGSAVE命令。 

當使用者開啟了觸發自動BGSAVE後,如果不配置save選項,伺服器會使用預設設定,如下:

  (1)在900秒內,對資料庫進行了至少1次修改。

(2)在300秒內,對資料庫進行了至少10次修改。

(3)在60秒內,對資料庫進行了至少10000次修改。

以上三個條件,滿足任意一條,就會進行BGSAVE操作

3、AOF持久化

AOF持久化與RDB不同,AOF持久化是通過記錄伺服器所執行的命令來儲存資料的。

    • 被寫入AOF檔案的所有命令都是以Redis請求協議格式儲存的。
    • 資料的還原,就是通過讀取AOF檔案的這些命令進行的。
    • 執行的命名並不是直接寫入AOF檔案的,而是先寫入緩衝區,沒執行一條命令就會追加到緩衝區的末尾,當一條命令執行完成後,返回資料前,會將緩衝區的資料寫入到AOF檔案中。

AOF檔案的載入與還原

AOF持久化的資料還原過程就是讀取AOF中命令重新執行命令的過程。

(1)Redis會建立一個偽客戶端,偽客戶端與真實的客戶端執行命令的效果是一樣的,只是不帶網路連線。

(2)從AOF檔案分析並讀取一條命令。

(3)偽客戶端執行這條命令。

(4)重複2和3過程,知道AOF檔案中的所有命令處理完成。

AOF檔案重寫

AOF檔案的持久化是記錄被執行對的命令,這樣隨著時間越來越長,AOF檔案中的內容會越來越多,體積也會越來越大,檔案越大恢復資料的時間也越多。

在命令執行的過程中有些鍵值對被刪除了,有些被修改了,而這些過程命令是完全沒有必要再執行一遍的,所以Redis提供了AOF檔案的重寫功能對AOF進行重建,使用重建後的檔案要比元AOF檔案體積小很多。

    • AOF檔案重寫,並不需要對原AOF檔案進行任何訪問改動,他是通過對資料庫內的資料讀取來操作的,即檢視資料庫內有什麼資料,然後根據資料型別進行建立這些資料的寫入命令。
    • AOF檔案重寫過程中,建立寫入命令時會先檢查元素數量,如果數量超過了redis.h/REDIS_AOF_REWRITE_ITEMS_PER_CMD=64常量的值,就會分成多條命令,
    • AOF檔案重寫是有子程式進行的,並不影響主程式處理命令;子程式而不是執行緒,因為程式帶有資料副本,不鎖資料的情況下,能保證安全。
    • AOF檔案子程式重寫過程中,主程式仍然在處理資料,這樣造成了子程式和主程式的資料不一致,子程式資料少了一部分,這種情況下Redis會建立一個AOF重寫緩衝區;這樣少的那部分命令會寫到AOF重寫緩衝區中,重寫完成後,再把緩衝區這些命令寫進新的AOF檔案中,然後用新的AOF檔案替換就得AOF檔案。

4、總結

    • Redis初始化會建立一批資料庫,每個資料庫的內部資料結構都是字典,key-value的最終儲存也會落到字典上。
    • AOF持久化比RDB持久化頻率更高、速度更快;當有AOF持久化時,RDB持久化命令不會再執行;但當RDB持久化命令執行時,AOF命令會等待其執行完成後再執行,而其他RDB命令不會執行。
    • AOF檔案重寫過程不會影響舊的AOF檔案,即便AOF重寫過程失敗,也不會干擾原來的AOF恢復資料,只有在成功之後才會替換原來的檔案。

 

參考:

《Redis設計與實現》黃健巨集著,網上對Redis的詳解等

此部落格為筆者使用redis很久之後,參考網路上各類文章總結性書寫,原創手打,如有錯誤歡迎指正。

相關文章