Redis设计与实现RDB持久化
什么是RDB持久化?
-
RDB持久化就是將Redis在內(nèi)存中產(chǎn)生的數(shù)據(jù)保存在磁盤里,防止數(shù)據(jù)的丟失。(Redis是一個內(nèi)存數(shù)據(jù)庫,一旦進(jìn)程退出,數(shù)據(jù)庫狀態(tài)也就消失不見了)
-
RDB文件是一個二進(jìn)制文件,保存的是某一個時間點(diǎn)的數(shù)據(jù)狀態(tài)。
RDB的文件結(jié)構(gòu)
完整的RDB文件包含以下部分
|REDIS|db_version|databases|EOF|check_sum|
-
REDIS:長度五個字節(jié),保存的REDIS這幾個字母(不是字符串),RDB文件的標(biāo)識符。
-
db_version:四個字節(jié)記錄RDB的版本號。
-
database:保存0個或多個數(shù)據(jù)庫,和各個數(shù)據(jù)庫的鍵值對數(shù)據(jù)。
-
EOF:一字節(jié),標(biāo)志RDB文件正文結(jié)束。
-
check_sum:八字節(jié)無符號整數(shù),由前四部份計算得來,用于檢查RDB文件是否由出錯或者受損的狀況。
database中存不同的類型值方式是不同的,下邊是數(shù)據(jù)庫的結(jié)構(gòu)
|SELECTDB|db_number|key_value-pairs|
-
SELECTDB:是一個長度為1字節(jié)的常量,它表示下一個要讀的是數(shù)據(jù)庫號碼
-
db_number:保存的是數(shù)據(jù)庫號碼
-
key_value_pairs:保存當(dāng)前數(shù)據(jù)庫的所有鍵值對,過期的也會保存在里面,根據(jù)過期種種原因,因此長度也不同。
-
沒過期的鍵值對由|TYPE|key|value|三部分組成。
-
key是一個字符串對象
-
value的結(jié)構(gòu)和長度和TYPE有關(guān)。
-
帶有過期鍵的在RDB由|EXPIRETIME_MS|TYPE||key|value|,EXPIRETIME標(biāo)識的是接下來要讀的是一個過期時間以毫秒為單位。
-
上邊說到value的值是不定的,下面對每一種情況進(jìn)行分析
字符串對象:字符串對象的編碼可以是int也可以是row,最大是32位的int(由8位,16位,32位)。如果是row的話,如果字符串的長度小于等于20,原樣保存。如果大于20,就會被壓縮(LZF算法)后再保存。
list對象:按照|list_length|item1|item2|…|itemN|保存。
集合對象:按照|set_size|elem1|elem2|…|elemN|保存。
哈希表對象:按照|hash_size|key1|value1|key2|value2|…|keyN|valueN|
有序集合:按照|sorted_set_size|member1|score1|member2|score2|…|memberN|scoreN|
整數(shù)集合(INTSET):先將整數(shù)集合化為字符串對象保存再RDB文件中,在讀入RDB文件時,根據(jù)TYPE值,讀入此字符串,然后將此字符串轉(zhuǎn)為原來的整數(shù)集合對象。
7.ZIPLIST,Zip_hashtable,Zset_Ziplist(有序集合):使用ZipList編碼的,value就是一個壓縮列表。這種文件存入RDB的步驟是,先將壓縮列表換為一個字符串對象,并存入RDB。讀入的時候?qū)⑺D(zhuǎn)換為原來的壓縮列表對象(因?yàn)槿际菈嚎s列表,不存在其他類型),然后根據(jù)TYPE的值來設(shè)置壓縮列表對象的類型。
RDB文件的生成
-
SAVE方法:會阻塞Redis服務(wù)器的進(jìn)程,直到RDB文件創(chuàng)建完畢。在此阻塞期間,服務(wù)器不能處理任何命令請求。
-
BGSAVE方法:會派生出一個子進(jìn)程,子進(jìn)程負(fù)責(zé)創(chuàng)建RDB文件(完成或出錯時會給父進(jìn)程發(fā)信號),父進(jìn)程繼續(xù)處理命令。然后父進(jìn)程一直輪詢,等待子進(jìn)程的信號。 在BGSAVE執(zhí)行期間,客戶端發(fā)送的SAVE,和BGSAVE會被服務(wù)器拒絕以免發(fā)生競爭(SAVE命令父進(jìn)程和子進(jìn)程同時調(diào)用rdbSAVE,BGSAVE子進(jìn)程和子進(jìn)程之間同時調(diào)用rdbSAVE)。
-
設(shè)置條件并自動間隔性保存:Redis允許通過設(shè)置save選項來讓服務(wù)器每隔一段事件自動執(zhí)行BGSAVE命令(在滿足設(shè)置的條件的情況下)。條件保存在reidserver中的*saveparams結(jié)構(gòu)體數(shù)組里。
在redis除了saveparams數(shù)組還有幾個重要的屬性,dirty計數(shù)器,記錄距離上次成功執(zhí)行SAVE或者BGSAVE命令后服務(wù)器對所有數(shù)據(jù)庫進(jìn)行了多少次修改。每一條修改命令都會讓它加一。
lastsave是一個UNIX時間戳,記錄上一次SAVE或BGSAVE執(zhí)行成功的事件。
serverCron是一個周期性操作函數(shù),每個100毫秒執(zhí)行一次,用于維護(hù)數(shù)據(jù)庫,使命之一就是檢查save的條件是否滿足,如果滿足就執(zhí)行BGSAVE。
RDB文件的載入和AOF文件的載入比較
-
RDB文件在服務(wù)器啟動時自動載入,只要檢測到RDB文件就自動載入并處于阻塞狀態(tài),直到載入完成。
-
AOF文件的優(yōu)先級高于RDB文件,如果服務(wù)器開啟了AOF持久化功能,則在重啟時會加載AOF文件,而不是RDB。(AOF通常更新頻率高于RDB文件)
-
如果AOF持久化關(guān)閉,才回去找RDB文件。
進(jìn)一步分析RDB文件
清空并保存為RDB文件。
打開已存的RDB文件,雖然是亂碼也隱隱約約能看到REDIS字符串,version,ctime,還有一些常量。(空的RDB文件由REDIS字符串,version,EOF常量和Check_Sum組成)
存一個值后會明顯發(fā)現(xiàn)下面多了一個字段(mesg)
雖然是亂碼還是能大致的發(fā)現(xiàn)和我們前邊說的結(jié)構(gòu)大致相同。(有值的數(shù)據(jù)庫有三部分組成,SELECTDB,db_number,key_value_pairs)
包含一個帶有過期時間的字符串鍵的RDB文件。(帶有過期鍵的RDB文件由EXPIRETIME_MS,ms,TYPE,key,value組成)
總結(jié)
以上是生活随笔為你收集整理的Redis设计与实现RDB持久化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Redis的设计与实现之对象
- 下一篇: Redis设计与实现AOF持久化