圖解Redis之持久化篇
持久化
Redis是典型的key-value型資料庫,我們通常把伺服器的非空資料庫及鍵值對統稱為資料庫狀態
因為Redis是內存資料庫,它把自己的資料庫狀態存儲在內存中,所以一旦發生停電或者其他因素使主機宕機,那麼數據將會丟失,所以Redis引入了持久化操作,它把Redis在內存中的資料庫狀態持久化到硬碟,當伺服器重新啟動的時候,去載入硬碟中的持久化文件就可恢復現場狀態.
Redis有兩種持久化方式:RDB持久化和AOF持久化,前者是通過把資料庫狀態的鍵值對保存起來,而AOF則是把命令保存起來,那麼伺服器是使用哪種持久化呢?因為AOF文件更新頻率更高,所以優先AOF.接下來將分別介紹兩種持久化方式
RDB持久化
- 創建RDB文件:
- 持久化策略
由於bgsave會創建子進程來進行持久化操作,並不阻礙伺服器進程處理其他事,所以我們可以讓伺服器每隔一段時間執行一次bgsave,因此可以通過設置保存條件來讓伺服器執行bgsave操作.
struct redisServer{ //... struct saveparam *saveparam;//記錄了保存條件的數組 sds aof_buf //AOF緩衝區,用來存放寫命令的協議請求內容 //...};//條件:當滿足條件(在time_t秒內,修改次數達到changes)時,伺服器執行bgsavestruct saveparam{ time_t seconds;//秒數 int changes//修改數};
好,現在我們真正講述Redis是如何檢查保存條件滿足與否!
Redis伺服器有個周期性函數serverCron,默認每隔100ms執行一次,Redis就是通過它來檢測保存條件
介紹到這裡,我們我們已經知道RDB持久化操作的時機和方式,接下來一起看看RDB的文件結構.- REDIS長度5位元組,保存著R E D I S 五個字元,可用來判斷文件是否是rdb文件
- db_version長度為4位元組,值為整數型字元串,代表rdb文件的版本號.比如0006
- databases 資料庫狀態,包含一個或多個資料庫,以及各個資料庫中的鍵值對
- EOF常量,1位元組,標誌著rdb文件的結束
- check_sum:8位元組的校驗和,程序通過對REDIS,db_version,databases,EOF四部分計算得來,伺服器載入rdb文件時,會將文件計算得來的校驗和與該值對比,依次來檢測rdb文件正確性.
- databases
SELECTDB常用為1位元組,當程序讀到這個值時,知道自己要選擇資料庫,db_number資料庫號,
key_value_pairs為當前資料庫中所有的鍵值對
- key_value_pairs:
- Type有以下幾種類型
REDIS_RDB_TYPE_STRING REDIS_RDB_TYPE_LIST REDIS_RDB_TYPE_LIST_ZIPLISTREDIS_RDB_TYPE_SET REDIS_RDB_TYPE_SET_INTSETREDIS_RDB_TYPE_ZSET REDIS_RDB_TYPE_ZSET_ZIPLIST REDIS_RDB_TYPE_HASH REDIS_RDB_TYPE_HASH_ZIPLIST
- value的編碼
- 字元串對象:字元串對象的格式主要分為兩種,一種是原樣,一種是壓縮後的,int型字元串原樣輸出,raw編碼的如果長度大於20byte採取壓縮形式,否則和int型相同.分別如下所示
- 列表對象
- 集合對象(同列表)
- 集合對象:同集合,不過是元素項開頭加了一個score
- 哈希表對象:依次table_size key1 value1 key2 value2
- INTSET 整數集合
- ziplist編碼的列表,哈希表或有序集合
AOF持久化
與RDB持久化保存資料庫中的鍵值對來記錄資料庫不同,AOF持久化是通過記錄Redis伺服器所執行的寫命令來記錄資料庫狀態的.那麼AOF持久化具體怎麼實現的呢?
AOF持久化的功能實現可描述為命令追加(append),文件寫入,文件同步(sync)三個步驟
- 命令追加:伺服器每執行一次寫命令,就把對應的命令請求協議內容添加到aof_buf緩衝區
- 文件寫入和文件同步
AOF文件的載入與數據還原
AOF重寫
由於AOF文件更行頻率很高,用戶會有大量的寫命令,如果每次都記錄,則會浪費大量空間,所以Redis實現了AOF重寫功能:首先從資料庫中讀取鍵現在的值,然後用一條命令去記錄鍵值對,代替之前記錄這個鍵值對的多條命令
AOF後台重寫
由於redis會伴隨大量的寫入操作,如果伺服器去執行aof重寫,則可能長時間阻塞,於是伺服器使用子進程來進行aof重寫,子進程持有伺服器進程的數據副本.然而在子進程每次重寫期間,伺服器又會有新的寫請求,那麼如何解決這個數據不一致問題呢?
為了解決這個問題,Redis伺服器設置了一個aof重寫緩衝區,在創建了子進程時,開始使用緩衝區,在子進程重寫期間,每當Redis伺服器有新的寫操作,都會把命令同時發給aof緩衝區和重寫緩衝區,這樣一來
- AOF緩衝區的內容會定期被寫人和同步到AOF文件,對現有AOF文件的處理工作如常進行。
- 從創建子進程開始,伺服器執行的所有寫命令都會被記錄到AOF重寫緩衝區裡面.
- 將AOF重寫緩衝區中的所有內容寫入到新AOF文件中,這時新AOF文件所保存的資料庫狀態將和伺服器當前的資料庫狀態一致。
- 對新的AOF文件進行改名,原子地(atomic)覆蓋現有的AOF文件,完成新舊兩個AOF文件的替換。
推薦閱讀:
※Spring Boot使用Redis進行消息的發布訂閱
※No-SQL資料庫中的事務性設計
※Redis源碼剖析--內存分配
※redis使用消息隊列的場合?
TAG:Redis |