RDB持久化
Redis是內(nèi)存數(shù)據(jù)庫墓贿,數(shù)據(jù)庫狀態(tài)都在內(nèi)存里邊祥款,需要RDB持久化功能將內(nèi)存中的數(shù)據(jù)庫狀態(tài)保存到磁盤里较锡,避免數(shù)據(jù)丟失。
SAVE和BGSAVE命令可用于生成RDB文件:
- SAVE:阻塞redis服務(wù)器進(jìn)程伏钠,直到RDB文件創(chuàng)建完畢横漏;
- BGSAVE:派生出一個子進(jìn)程負(fù)責(zé)創(chuàng)建RDB文件,父進(jìn)程繼續(xù)處理請求熟掂。
RDB文件的載入是有服務(wù)器啟動時自動執(zhí)行的缎浇,服務(wù)器會阻塞知道RDB文件被載入完成。
AOF文件的更新頻率比RDB文件高赴肚,所以如果服務(wù)器開啟了AOF持久化功能华畏,那么會優(yōu)先使用AOF文件來還原數(shù)據(jù)庫狀態(tài)鹏秋。
RDB文件結(jié)構(gòu)(RDB保存的是二進(jìn)制數(shù)據(jù))
- REDIS:保存“REDIS”五個字符,可以快速檢查所載入的文件是否為RDB'文件亡笑;
- db_version:版本號侣夷,4字節(jié)字符串表示的整數(shù);
- database:包含0個或多個數(shù)據(jù)庫仑乌,以及各個數(shù)據(jù)庫中的鍵值對數(shù)據(jù)百拓;
- EOF:1字節(jié),標(biāo)志RDB文件正文內(nèi)容結(jié)束晰甚,鍵值對加載完畢衙传;
- check_sum:檢驗和,8字節(jié)的無符號整數(shù)厕九。
database:RDB文件中的數(shù)據(jù)庫結(jié)構(gòu)
- SELECTDB:常量蓖捶,1字節(jié),讀到這個值時便知道接下來就是數(shù)據(jù)庫號碼扁远;
- db_number:保存一個數(shù)據(jù)庫號碼俊鱼,可以是1字節(jié)、2字節(jié)或5字節(jié)畅买;
-
key_value_pairs:保存了數(shù)據(jù)庫中所有的鍵值對數(shù)據(jù)并闲,以及對應(yīng)的過期時間。
image
image
TYPE:記錄value的類型谷羞,1字節(jié)帝火;代表了一種對象類型或者底層編碼,程序會根據(jù)TYPE的值來決定如何讀入和解釋value數(shù)據(jù):
- REDIS_RDB_TYPE_STRING
- REDIS_RDB_TYPE_LIST
- REDIS_RDB_TYPE_SET
- REDIS_RDB_TYPE_ZSET
- REDIS_RDB_TYPE_HASH
- REDIS_RDB_TYPE_LIST_ZIPLIST
- REDIS_RDB_TYPE_SET_INTSET
- REDIS_RDB_TYPE_ZSET_ZIPLIST
- REDIS_RDB_TYPE_HASH_ZIPLIST
key:字符串對象湃缎;
value:值對象犀填,類型記錄在TYPE中:
- 字符串對象:REDIS_RDB_TYPE_STRING
編碼為REDIS_ENCODING_INT,則保存對象是長度不超過32位的整數(shù):
image
編碼為REDIS_ENCODING_RAW嗓违,則保存對象為字符串九巡,若長度小于等于20字節(jié)則原字符串保存:
image
若長度大于20字節(jié)則壓縮保存:
image -
列表對象:REDIS_RDB_TYPE_LIST,編碼:REDIS_ENCODING_LINKEDLIST
image - 集合對象:
REDIS_RDB_TYPE_SET靠瞎,編碼:REDIS_ENCODING_HT
[圖片上傳失敗...(image-8007a2-1525337873697)]
REDIS_RDB_TYPE_SET_INTSET:編碼:REDIS_ENCODING_INTSET
將整數(shù)集合轉(zhuǎn)換為字符串對象,然后將字符串對象保存到RDB文件中 -
哈希表對象:REDIS_RDB_TYPE_HASH求妹,編碼:REDIS_ENCODING_HT
image -
有序集合對象:REDIS_RDB_TYPE_ZSET乏盐,編碼:REDIS_ENCODING_SKIPLIST
image - ZIPLIST編碼的列表(REDIS_RDB_TYPE_LIST_ZIPLIST)、哈希表(REDIS_RDB_TYPE_HASH_ZIPLIST)或有序集合(REDIS_RDB_TYPE_ZSET_ZIPLIST):均將壓縮列表轉(zhuǎn)換成一個字符串對象再保存到RDB文件中制恍,讀取RDB文件時再根據(jù)TYPE值還原成對應(yīng)的類型對象父能。
EXPIRETIME_MS:常量,1字節(jié)净神,告知程序接下來是以毫秒為單位的過期時間何吝;
ms:8字節(jié)帶符號整數(shù)溉委,記錄一個以毫秒為單位的UNIX時間戳。
AOF持久化
AOF(Append Only File)持久化是通過保存Redis服務(wù)器所執(zhí)行的寫命令來記錄數(shù)據(jù)庫狀態(tài)爱榕。服務(wù)器啟動時瓣喊,可以通過載入和執(zhí)行AOF文件中保存的命令來還原服務(wù)器關(guān)閉之前的數(shù)據(jù)庫狀態(tài)。
AOF功能包括三個步驟:命令追加黔酥、文件寫入和文件同步藻三。
1、命令追加:服務(wù)器執(zhí)行完一個寫命令后跪者,會以協(xié)議格式將被執(zhí)行的寫命令追加到服務(wù)器狀態(tài)的aof_buf緩沖區(qū)的末尾棵帽;
2、文件寫入與文件同步:服務(wù)器進(jìn)程是一個事件循環(huán)渣玲,在一次事件循環(huán)結(jié)束之前逗概,都會調(diào)用flushAppendOnlyFile函數(shù),并由配置參數(shù)appendfsync選項決定aof_buf緩沖區(qū)中的內(nèi)容是否寫入和保存到AOF文件中忘衍,具體設(shè)置如下:
寫入不會阻塞到IO完成才返回逾苫,因此若在此期間發(fā)生故障會造成數(shù)據(jù)丟失;
同步是通過同步IO原語來提供os級別的保證淑履,保證文件所有已修改的內(nèi)容同步到磁盤中隶垮。
AOF文件載入與還原
AOF重寫:AOF持久化是通過保存被執(zhí)行的寫命令來記錄數(shù)據(jù)庫狀態(tài)的,所以AOF文件中的內(nèi)容會越來越多秘噪,造成影響狸吞。AOF重寫是通過讀取當(dāng)前的數(shù)據(jù)庫狀態(tài),從而得到一個新的AOF文件指煎,其體積較小蹋偏,但跟原來的AOF文件所保存的數(shù)據(jù)庫狀態(tài)是一樣的。其原理就是從數(shù)據(jù)庫中讀取每個鍵現(xiàn)在的值至壤,然后用一條命令去記錄鍵值對(但當(dāng)處理列表威始、哈希表、集合或有序集合這些帶有多個元素的鍵時像街,若元素數(shù)量超過64個黎棠,會用多條命令來記錄鍵值對)。
AOF后臺重寫:
AOF重寫會造成服務(wù)器進(jìn)程阻塞而無法處理其他命令請求镰绎,因此Redis創(chuàng)建一個新的子進(jìn)程用于處理AOF重寫脓斩,這樣的好處是:
- 子進(jìn)程進(jìn)行AOF重寫期間,服務(wù)器進(jìn)程仍可以繼續(xù)處理命令請求畴栖;
- 子進(jìn)程帶有服務(wù)器進(jìn)程副本随静,使用子進(jìn)程而非線程,可以避免使用鎖的情況下保證數(shù)據(jù)的安全性。
為了解決子進(jìn)程在處理AOF重寫時燎猛,服務(wù)器進(jìn)程對數(shù)據(jù)庫狀態(tài)進(jìn)行修改而造成的不一致恋捆,Redis設(shè)置一個AOF重寫緩沖區(qū),在子進(jìn)程處理AOF重寫時重绷,服務(wù)器每執(zhí)行完一個寫命令沸停,會將該命令發(fā)送到AOF重寫緩沖區(qū),子進(jìn)程處理完畢后產(chǎn)生新的AOF文件论寨,并向服務(wù)器進(jìn)程發(fā)送一個信號星立,服務(wù)器進(jìn)程接收到該信號后就將AOF重寫緩沖區(qū)的命令追加到新的AOF文件中。