Redis RDB與AOF持久化方式詳細(xì)講解
1.RDB持久化
首先,RDB持久化方式會(huì)產(chǎn)生一個(gè)經(jīng)過壓縮的二進(jìn)制文件,Redis服務(wù)器在啟動(dòng)之初,通過這個(gè)文件可以還原數(shù)據(jù)庫(kù)的狀態(tài)。那么我們接下來看下RDB文件是如何實(shí)現(xiàn)保存和載入的。
1.1 RDB文件的保存
RDB文件的保存有兩個(gè)命令可以實(shí)現(xiàn),分別是save和bgsave,執(zhí)行后都會(huì)生成新的RDB文件,區(qū)別是save會(huì)阻塞服務(wù)器的進(jìn)程,直到RDB文件創(chuàng)建完成為止,期間服務(wù)器不能處理任何客戶端的命令請(qǐng)求。而bgsave通過派生出一個(gè)子進(jìn)程,由子進(jìn)程來完成RDB文件的創(chuàng)建,期間服務(wù)器正常處理客戶端的命令請(qǐng)求。其實(shí)這兩個(gè)命令的底層實(shí)現(xiàn)方式都一樣,只不過一個(gè)是主進(jìn)程來做,另一個(gè)是通過子進(jìn)程來完成。
在redis.conf文件中,有兩個(gè)參數(shù)是和rdb的文件保存相關(guān):
// 這個(gè)是rdb文件的名稱 dbfilename dump.rdb // 這個(gè)是rdb文件的保存路徑,這是相對(duì)路徑,相對(duì)于redis-server的啟動(dòng)路徑 dir ./
1.2 RDB文件的載入
在redis服務(wù)器啟動(dòng)之初,會(huì)去查找有沒有rdb的持久化文件存在,如果有就會(huì)自動(dòng)載入,當(dāng)然前提是沒有開啟aof持久化的功能。在rdb載入期間會(huì),服務(wù)器處于阻塞裝填,直到載入工作完全結(jié)束。
1.3 RDB持久化時(shí)服務(wù)器的狀態(tài)
save命令執(zhí)行期間,所有客戶端命令都會(huì)被拒絕執(zhí)行。
bgsave命令執(zhí)行期間,客戶端發(fā)送的save和bgsave命令會(huì)被拒絕執(zhí)行,但是客戶端發(fā)送的bgrewriteaof不會(huì)拒絕但會(huì)被阻塞,直到當(dāng)前的bgsave命令執(zhí)行完畢。但是值得說明的是,如果服務(wù)器在執(zhí)行bgrewriteaof命令期間,客戶端發(fā)送的bgsave命令會(huì)被服務(wù)器拒絕。當(dāng)然這是站在性能角度考慮,否則fock出兩個(gè)子進(jìn)程,大量的進(jìn)行磁盤的讀寫,會(huì)影響整個(gè)服務(wù)器的性能。
1.4 RDB持久化策略
用戶可以通過配置文件給RDB的持久化設(shè)置保存策略,看一下redis.conf文件中的配置:
save 900 1
save 300 10
save 60 10000
以上的默認(rèn)配置可以表示為:服務(wù)器在900秒之內(nèi),至少進(jìn)行了1次的修改,在300秒之內(nèi)至少進(jìn)行了10次修改,在60秒之內(nèi)至少進(jìn)行了10000次修改。這三種策略只要滿足一個(gè),即可觸發(fā)RDB的持久化。
這里需要了解一下,Redis是怎么基于這些配置策略實(shí)現(xiàn)自動(dòng)化間歇性保存RDB文件的,還是回到RedisServer這個(gè)這個(gè)結(jié)構(gòu)體的源碼中看一下:
struct redisServer {
// 數(shù)組,用于保存redis.conf配置的持久化策略
struct saveparam *saveparams; /* Save points array for RDB */
// 上面這個(gè)數(shù)組的長(zhǎng)度
int saveparamslen; /* Number of saving points */
// 記錄上一次持久化到現(xiàn)在服務(wù)器修改了多少鍵值對(duì)
long long dirty; /* Changes to DB from the last save */
// 記錄上一次RDB持久化的UNIX時(shí)間戳
time_t lastsave; /* Unix time of last successful save */
}
在redisServer中,有saveparams數(shù)組專門保存我們配置的持久化策略,這里使用到了saveparam這個(gè)結(jié)構(gòu)體,看一下源碼:
struct saveparam {
// 這里是配置文件save的第1個(gè)參數(shù)
time_t seconds;
// 這里是配置文件save的第2個(gè)參數(shù)
int changes;
};
這樣,配置文件中的持久化策略就記錄到了redisServer.saveparam屬性中,還是會(huì)基于serverCron這個(gè)時(shí)間事件函數(shù),100ms執(zhí)行一次,每次會(huì)檢查 dirty 和 lastsave 記錄的修改鍵值對(duì)數(shù)量和時(shí)間差,是否匹配到了saveparam中配置的持久化策略,如果命中就進(jìn)行新一輪的RDB持久化。
2.AOF持久化
和RDB不同,AOF是通過記錄Redis服務(wù)器中執(zhí)行的寫命令來記錄數(shù)據(jù)庫(kù)狀態(tài)的,類似于mysql的binlog,當(dāng)然保存的內(nèi)容是經(jīng)過協(xié)議轉(zhuǎn)換的命令。在服務(wù)器啟動(dòng)之初,通過載入和執(zhí)行AOF文件中的命令來還原數(shù)據(jù)庫(kù)的狀態(tài)。
2.1 持久化的實(shí)現(xiàn)
在服務(wù)器執(zhí)行命令之后,并不是立刻寫入aof文件中,而是先寫入 aof_buf緩沖區(qū)里面,這也是redisServer的一個(gè)屬性結(jié)構(gòu):
struct redisServer {
// aop緩沖區(qū),記錄服務(wù)器寫入的命令
sds aof_buf; /* AOF buffer, written before entering the event loop */
}
我們?cè)倏匆幌聄edis.conf關(guān)于aof持久化的一個(gè)配置:
// 這個(gè)表示每次執(zhí)行都會(huì)寫入 # appendfsync always // 這個(gè)表示每秒寫入一次 appendfsync everysec // 這個(gè)由操作系統(tǒng)決定,無法控制 # appendfsync no
AOF實(shí)現(xiàn)持久化的原理是這樣的,客戶端執(zhí)行的命令會(huì)先記錄到 redisServer.aof_buf 中,然后基于配置文件的appendfsync策略決定什么時(shí)候同步到AOF文件中。這里的同步也會(huì)經(jīng)過兩個(gè)步驟:
- aof_buf 內(nèi)容寫入到操作系統(tǒng)文件緩存 pagecache;
- pagecache 落盤寫入到屋里磁盤設(shè)備中;
我們知道Redis是基于Reactor網(wǎng)絡(luò)模型,不斷進(jìn)行事件循環(huán),每進(jìn)行一輪的事件循環(huán),都會(huì)執(zhí)行步驟1,所以從aof_buf 到 pagecache總是會(huì)發(fā)生。但是步驟2就跟appendfsync有關(guān)系了:
- always表示只要步驟1發(fā)生,步驟2也會(huì)發(fā)生,所以是最安全,但是效率最慢的一個(gè)。
- everysec表示步驟1發(fā)生后,步驟2每秒執(zhí)行一次落盤,是效率和數(shù)據(jù)安全折中的方案,停機(jī)故障時(shí)有丟失1秒鐘數(shù)據(jù)的風(fēng)險(xiǎn)。
- no表示步驟1發(fā)生后,何時(shí)落盤由操作系統(tǒng)決定,數(shù)據(jù)丟失風(fēng)險(xiǎn)大,效率也一般,因?yàn)閿?shù)據(jù)量過大,單次落盤的時(shí)間也最長(zhǎng)。
默認(rèn)配置是everysec,即每秒執(zhí)行一次數(shù)據(jù)落盤保存。
2.2 文件的載入與數(shù)據(jù)還原
因?yàn)锳OF文件中包含了重建數(shù)據(jù)庫(kù)狀態(tài)的所有寫命令,所以服務(wù)器只要讀入并全部執(zhí)行一遍就可以完成數(shù)據(jù)庫(kù)狀態(tài)的還原。服務(wù)器在啟動(dòng)之初,會(huì)創(chuàng)建一個(gè)不帶網(wǎng)絡(luò)連接的偽客戶端來做這件事,在載入命令完成后,這個(gè)客戶端的使命就結(jié)束了。
2.3 AOF文件的重寫
隨著寫入到AOF文件的命令越來越多,這個(gè)文件體積會(huì)越來大,會(huì)對(duì)宿主機(jī)或文件還原造成一定的影響,所以需要通過AOF文件的重寫來解決文件體積膨脹的問題。
AOF文件重寫并不是對(duì)現(xiàn)有AOF文件進(jìn)行處理,而是基于數(shù)據(jù)庫(kù)當(dāng)前的狀態(tài)來實(shí)現(xiàn)的。服務(wù)器會(huì)從數(shù)據(jù)庫(kù)中讀取鍵對(duì)應(yīng)的值,然后用一條命令去記錄鍵值對(duì),代替之前可能存在的多條命令,寫入到一個(gè)新的AOF文件中,這就是AOF重寫功能實(shí)現(xiàn)的原理。需要注意的是,對(duì)于某些元素比較多的集合或者列表(默認(rèn)配置是64個(gè)),這個(gè)一條命令可能拆分成多條實(shí)現(xiàn),避免造成客戶端輸入緩沖區(qū)溢出的情況。
和bgsave一樣,AOF重寫的動(dòng)作也是放到子進(jìn)程去執(zhí)行,這樣可以保證父進(jìn)程可以繼續(xù)處理名請(qǐng)求。但是這里會(huì)有一個(gè)問題,就是AOF文件重寫期間,父進(jìn)程處理命令請(qǐng)求之后,會(huì)和重寫AOF文件時(shí)的數(shù)據(jù)庫(kù)狀態(tài)不一致。Redis解決這個(gè)問題的方法是設(shè)置一個(gè)AOF重寫緩沖區(qū),子進(jìn)程一單創(chuàng)建并且開始重寫命令之后,父進(jìn)程處理的所有寫命令請(qǐng)求都會(huì)記錄到AOF重寫緩沖區(qū)。當(dāng)子進(jìn)程重寫工作完成之后,會(huì)生成一個(gè)新的AOF文件,向父進(jìn)程發(fā)送一個(gè)信號(hào),父進(jìn)程在接受此信號(hào),開始執(zhí)行以下工作:
- 將AOF重寫緩沖區(qū)的內(nèi)容寫入到新的AOF文件中,保證新文件和服務(wù)器當(dāng)前的狀態(tài)一致;
- 對(duì)新的AOF文件改名,并原子的替換現(xiàn)有的AOF文件,完成新舊文件的替換。
以上兩步,父進(jìn)程會(huì)造成服務(wù)器進(jìn)程的阻塞,但其他時(shí)間,都不會(huì)阻塞,整個(gè)重寫動(dòng)作對(duì)服務(wù)器性能的影響降到了最低,以上就是bgrewriteaof命令的實(shí)現(xiàn)原理。

到此這篇關(guān)于Redis RDB與AOF持久化方式詳細(xì)講解的文章就介紹到這了,更多相關(guān)Redis RDB與AOF內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
odoo中使用redis實(shí)現(xiàn)緩存的步驟
這篇文章主要介紹了odoo中使用redis實(shí)現(xiàn)緩存的步驟,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-04-04
解讀redis?slaveof命令執(zhí)行后為什么需要清庫(kù)重新同步
這篇文章主要介紹了redis?slaveof命令執(zhí)行后為什么需要清庫(kù)重新同步,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-04-04
Redis全文搜索教程之創(chuàng)建索引并關(guān)聯(lián)源數(shù)據(jù)的教程
RediSearch提供了一種簡(jiǎn)單快速的方法對(duì) hash 或者 json 類型數(shù)據(jù)的任何字段建立二級(jí)索引,然后就可以對(duì)被索引的 hash 或者 json 類型數(shù)據(jù)字段進(jìn)行搜索和聚合操作,這篇文章主要介紹了Redis全文搜索教程之創(chuàng)建索引并關(guān)聯(lián)源數(shù)據(jù),需要的朋友可以參考下2023-12-12
Windows中Redis安裝配置流程并實(shí)現(xiàn)遠(yuǎn)程訪問功能
很多在windows環(huán)境中安裝Redis總是出錯(cuò),今天小編抽空給大家分享在Windows中Redis安裝配置流程并實(shí)現(xiàn)遠(yuǎn)程訪問功能,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2021-06-06
windows下通過批處理腳本啟動(dòng)redis的操作
本文主要給大家介紹了windows下通過批處理腳本啟動(dòng)redis的操作,windows下redis啟動(dòng),需要進(jìn)入redis安裝目錄,然后shift+右鍵,選擇“在此處打開命令窗口”,然后輸入redis-server.exe redis.conf,就可以啟動(dòng)redis了,文中有詳細(xì)的圖文參考,感興趣的朋友可以參考下2023-12-12

