小編給大家分享一下redis中持久化機(jī)制是怎么樣的,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!
成都創(chuàng)新互聯(lián)公司堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:網(wǎng)站設(shè)計(jì)、成都做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的榆社網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!
為什么要持久化
如果Redis再次訪問時(shí),發(fā)現(xiàn)Redis的數(shù)據(jù)是空的,就會(huì)形成緩存穿透。更重要的是,因?yàn)镽edis的數(shù)據(jù)是空的,所以客戶端想要訪問的key都沒有,就會(huì)造成大量的請(qǐng)求就會(huì)瞬間打到數(shù)據(jù)庫上,造成緩存雪崩(少量的key是穿透,大量的key是雪崩)。
這個(gè)時(shí)候,數(shù)據(jù)庫可能就掛掉。而又無法保證redis不宕機(jī),所以需要當(dāng)redis宕機(jī)后,迅速將里里面的內(nèi)容恢復(fù)出來。因此需要做一個(gè)持久化。持久化是為了恢復(fù)數(shù)據(jù)用的,而不是存儲(chǔ)數(shù)據(jù)用的。
RDB
RDB(Redis DataBase),是Redis默認(rèn)的存儲(chǔ)方式,RDB方式是通過快照(snapshotting)完成的。
觸發(fā)快照的方式
符合自定義配置的快照規(guī)則
save 900 1 # 表示15分鐘(900秒鐘)內(nèi)至少1個(gè)鍵被更改則進(jìn)行快照。
save 300 10 # 表示5分鐘(300秒)內(nèi)至少10個(gè)鍵被更改則進(jìn)行快照。
save 60 10000 # 表示1分鐘內(nèi)至少10000個(gè)鍵被更改則進(jìn)行快
N秒內(nèi)數(shù)據(jù)集至少有M個(gè)改動(dòng)”這一條件被滿足時(shí),自動(dòng)保存一次數(shù)據(jù)集。
執(zhí)行save或者bgsave命令
執(zhí)行命令save或bgsave可以生成dump.rdb文件,每次命令執(zhí)行都會(huì)將所有redis內(nèi)存快照到一個(gè)新的rdb文件里,并覆蓋原有rdb快照文件。
save與bgsave對(duì)比:
| 命令 | save | bgsave |
|---|---|---|
| IO類型 | 同步 | 異步 |
| 是否阻塞redis其它命令 | 是 | 否(在生成子進(jìn)程執(zhí)行調(diào)用fork函數(shù)時(shí)會(huì)有短暫阻塞) |
| 復(fù)雜度 | O(n) | O(n) |
| 優(yōu)點(diǎn) | 不會(huì)消耗額外內(nèi)存 | 不阻塞客戶端命令 |
| 缺點(diǎn) | 阻塞客戶端命令 | 需要fork子進(jìn)程,消耗內(nèi)存 |
配置自動(dòng)生成rdb文件后臺(tái)使用的是bgsave方式。
執(zhí)行flushall命令
flushall
清空Redis之前,保存當(dāng)前Redis快照
執(zhí)行主從復(fù)制操作 (第一次)
第一次主從復(fù)制時(shí)需要生成rdb文件,會(huì)保存當(dāng)前Redis快照
RDB執(zhí)行流程
.jpg)
流程分析
父進(jìn)程fork子進(jìn)程后,繼續(xù)工作。
子進(jìn)程發(fā)送信號(hào)給父進(jìn)程表示完成,父進(jìn)程更新統(tǒng)計(jì)信息。
子進(jìn)程創(chuàng)建RDB文件,根據(jù)父進(jìn)程內(nèi)存快照生成臨時(shí)快照文件,完成后對(duì)原有文件進(jìn)行原子替換。(RDB始終完整)
父進(jìn)程fork后,bgsave命令返回”Background saving started”信息并不再阻塞父進(jìn)程,并可以響應(yīng)其他命令。
父進(jìn)程執(zhí)行fork(調(diào)用操作系統(tǒng)函數(shù)復(fù)制主進(jìn)程)操作創(chuàng)建子進(jìn)程,這個(gè)過程中父進(jìn)程是阻塞的,Redis不能執(zhí)行來自客戶端的任何命令。
Redis父進(jìn)程首先判斷:當(dāng)前是否在執(zhí)行save或bgsave/bgrewriteaof(aof文件重寫命令)的子進(jìn)程,如果在執(zhí)行則bgsave命令直接返回。
RDB文件結(jié)構(gòu)
.jpg)
1、頭部5字節(jié)固定為“REDIS”字符串
2、4字節(jié)“RDB”版本號(hào)(不是Redis版本號(hào)),當(dāng)前為9,填充后為0009
3、輔助字段,以key-value的形式
4、存儲(chǔ)數(shù)據(jù)庫號(hào)碼
5、字典大小
6、過期key
7、主要數(shù)據(jù),以key-value的形式存儲(chǔ)
8、結(jié)束標(biāo)志
9、校驗(yàn)和,就是看文件是否損壞,或者是否被修改
RDB的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
RDB是二進(jìn)制壓縮文件,占用空間小,便于傳輸(傳給slaver)
主進(jìn)程fork子進(jìn)程,可以最大化Redis性能,主進(jìn)程不能太大,復(fù)制過程中主進(jìn)程阻塞
缺點(diǎn)
不保證數(shù)據(jù)完整性,會(huì)丟失最后一次快照以后更改的所有數(shù)據(jù)
AOF
AOF(append only file)是Redis的另一種持久化方式。Redis默認(rèn)情況下是不開啟的。開啟AOF持久化后,Redis將所有對(duì)數(shù)據(jù)庫進(jìn)行過寫入的命令(及其參數(shù))(RESP)記錄到AOF文件,以此達(dá)到記錄數(shù)據(jù)庫狀態(tài)的目的,
這樣當(dāng)Redis重啟后只要按順序回放這些命令就會(huì)恢復(fù)到原始狀態(tài)了。AOF會(huì)記錄過程,RDB只管結(jié)果
AOF持久化實(shí)現(xiàn)
配置 redis.conf
# 可以通過修改redis.conf配置文件中的appendonly參數(shù)開啟 appendonly yes # AOF文件的保存位置和RDB文件的位置相同,都是通過dir參數(shù)設(shè)置的。 dir ./ # 默認(rèn)的文件名是appendonly.aof,可以通過appendfilename參數(shù)修改 appendfilename appendonly.aof
AOF原理
AOF文件中存儲(chǔ)的是redis的命令,同步命令到 AOF 文件的整個(gè)過程可以分為三個(gè)階段:
命令傳播:Redis將執(zhí)行完的命令、命令的參數(shù)、命令的參數(shù)個(gè)數(shù)等信息發(fā)送到 AOF 程序中。
緩存追加:AOF程序根據(jù)接收到的命令數(shù)據(jù),將命令轉(zhuǎn)換為網(wǎng)絡(luò)通訊協(xié)議的格式,然后將協(xié)議內(nèi)容追加 到服務(wù)器的AOF緩存中。
文件寫入和保存:AOF 緩存中的內(nèi)容被寫入到 AOF 文件末尾,如果設(shè)定的 AOF 保存條件被滿足的話, fsync函數(shù)或者fdatasync 函數(shù)會(huì)被調(diào)用,將寫入的內(nèi)容真正地保存到磁盤中。

命令傳播
當(dāng)一個(gè)Redis客戶端需要執(zhí)行命令時(shí),它通過網(wǎng)絡(luò)連接,將協(xié)議文本發(fā)送給Redis服務(wù)器。服務(wù)器在接到客戶端的請(qǐng)求之后,它會(huì)根據(jù)協(xié)議文本的內(nèi)容,選擇適當(dāng)?shù)拿詈瘮?shù),并將各個(gè)參數(shù)從字符串文本轉(zhuǎn)換為Redis 字符串對(duì)象(StringObject)。每當(dāng)命令函數(shù)成功執(zhí)行之后,命令參數(shù)都會(huì)被傳播到AOF程序。
緩存追加
當(dāng)命令被傳播到AOF程序之后,程序會(huì)根據(jù)命令以及命令的參數(shù),將命令從字符串對(duì)象轉(zhuǎn)換回原來的協(xié)議文本。協(xié)議文本生成之后,它會(huì)被追加到redis.h/redisServer結(jié)構(gòu)的aof_buf 末尾。
redisServer結(jié)構(gòu)維持著Redis服務(wù)器的狀態(tài),aof_buf域則保存著所有等待寫入到AOF 文件的協(xié)議文本(RESP)
文件寫入和保存
每當(dāng)服務(wù)器常規(guī)任務(wù)函數(shù)被執(zhí)行、或者事件處理器被執(zhí)行時(shí),aof.c/flushAppendOnlyFile 函數(shù)都會(huì)被調(diào)用,這個(gè)函數(shù)執(zhí)行以下兩個(gè)工作:
WRITE:根據(jù)條件將aof_buf中的緩存寫入到AOF文件。
SAVE:根據(jù)條件調(diào)用fsync或 fdatasync函數(shù)將AOF文件保存到磁盤中。
AOF保存模式
Redis 目前支持三種 AOF 保存模式,它們分別是:
AOF_FSYNC_NO :不保存。
AOF_FSYNC_EVERYSEC :每一秒鐘保存一次。(默認(rèn))
AOF_FSYNC_ALWAYS :每執(zhí)行一個(gè)命令保存一次。(不推薦)
AOF_FSYNC_NO
從不fsync,將數(shù)據(jù)交給操作系統(tǒng)來處理。更快,也更不安全的選擇。
SAVE只會(huì)在以下任意一種情況中被執(zhí)行:
Redis被關(guān)閉
AOF功能被關(guān)閉
系統(tǒng)的寫緩存被刷新(可能是緩存已經(jīng)被寫滿,或者定期保存操作被執(zhí)行)
這三種情況下的SAVE操作都會(huì)引起Redis主進(jìn)程阻塞。
AOF_FSYNC_EVERYSEC
SAVE原則上每隔一秒鐘就會(huì)執(zhí)行一次,因?yàn)镾AVE操作是由后臺(tái)子線程(fork)調(diào)用的, 所以它不會(huì)引起服務(wù)器主進(jìn)程阻塞,并且在故障時(shí)只會(huì)丟失1秒鐘的數(shù)據(jù)。
AOF_FSYNC_ALWAYS
每次執(zhí)行完一個(gè)命令之后,WRITE和SAVE都會(huì)被執(zhí)行。每次有新命令追加到AOF文件時(shí)就執(zhí)行一次fsync,非常慢,也非常安全。
因?yàn)镾AVE是由Redis主進(jìn)程執(zhí)行的,所以在SAVE執(zhí)行期間,主進(jìn)程會(huì)被阻塞,不能接受命令請(qǐng)求。
AOF保存模式對(duì)性能和安全性的影響
三種模式的比較
.jpg)
AOF重寫
AOF記錄數(shù)據(jù)的變化過程,越來越大,需要重寫“瘦身”
Redis可以在AOF體積變得過大時(shí),自動(dòng)地在后臺(tái)(Fork子進(jìn)程)對(duì)AOF進(jìn)行重寫。
重寫后的新AOF文件包含了恢復(fù)當(dāng)前數(shù)據(jù)集所需的最小命令集合。
所謂的“重寫”其實(shí)是一個(gè)有歧義的詞語,實(shí)際上,AOF重寫并不需要對(duì)原有的AOF文件進(jìn)行任何寫入和讀取,它針對(duì)的是數(shù)據(jù)庫中鍵的當(dāng)前值。
舉例說明
set s1 11 set s1 22 set s1 33 lpush list1 1 2 3 lpush list1 4 5 6
AOF重寫后
set s1 33 lpush list1 1 2 3 4 5 6
Redis不希望AOF重寫造成服務(wù)器無法處理請(qǐng)求,所以Redis決定將AOF重寫程序放到(后臺(tái))子進(jìn)程里執(zhí)行,
1、子進(jìn)程進(jìn)行AOF重寫期間,主進(jìn)程可以繼續(xù)處理命令請(qǐng)求。
2、子進(jìn)程帶有主進(jìn)程的數(shù)據(jù)副本,使用子進(jìn)程而不是線程,可以在避免鎖的情況下,保證數(shù)據(jù)的安全性。
不過,使用子進(jìn)程也有一個(gè)問題需要解決:因?yàn)樽舆M(jìn)程在進(jìn)行AOF重寫期間,主進(jìn)程還需要繼續(xù)處理命令,而新的命令可能對(duì)現(xiàn)有的數(shù)據(jù)進(jìn)行修改,這會(huì)讓當(dāng)前數(shù)據(jù)庫的數(shù)據(jù)和重寫后的AOF文件中的數(shù)據(jù)不一致。
為了解決這個(gè)問題,Redis增加了一個(gè)AOF重寫緩存,這個(gè)緩存在fork出子進(jìn)程之后開始啟用,Redis主進(jìn)程在接到新的寫命令之后,除了會(huì)將這個(gè)寫命令的協(xié)議內(nèi)容追加到現(xiàn)有的AOF文件之外,還會(huì)追加到這個(gè)緩存中。
重寫過程分析

Redis在創(chuàng)建新AOF文件的過程中,會(huì)繼續(xù)將命令追加到現(xiàn)有的AOF文件里面,即使重寫過程中發(fā)生停機(jī),現(xiàn)有的AOF文件也不會(huì)丟失。而一旦新AOF文件創(chuàng)建完畢,Redis就會(huì)從舊AOF文件切換到新AOF文件,并開始對(duì)新AOF文件進(jìn)行追加操作。
當(dāng)子進(jìn)程在執(zhí)行AOF重寫時(shí),主進(jìn)程需要執(zhí)行以下三個(gè)工作:
處理命令請(qǐng)求。
將寫命令追加到現(xiàn)有的AOF文件中。
將寫命令追加到AOF重寫緩存中
。這樣一來可以保證:現(xiàn)有的AOF功能會(huì)繼續(xù)執(zhí)行,即使在AOF重寫期間發(fā)生停機(jī),也不會(huì)有任何數(shù)據(jù)丟失。所有對(duì)數(shù)據(jù)庫進(jìn)行修改的命令都會(huì)被記錄到AOF重寫緩存中。
當(dāng)子進(jìn)程完成AOF重寫之后,它會(huì)向父進(jìn)程發(fā)送一個(gè)完成信號(hào),父進(jìn)程在接到完成信號(hào)之后,會(huì)調(diào)用一個(gè)信號(hào)處理函數(shù),并完成以下工作:
將AOF重寫緩存中的內(nèi)容全部寫入到新AOF文件中。
對(duì)新的AOF文件進(jìn)行改名,覆蓋原有的AOF文件。
Redis數(shù)據(jù)庫里的+AOF重寫過程中的命令------->新的AOF文件---->覆蓋老的當(dāng)步驟1執(zhí)行完畢之后,現(xiàn)有AOF文件、新AOF文件和數(shù)據(jù)庫三者的狀態(tài)就完全一致了。
當(dāng)步驟2執(zhí)行完畢之后,程序就完成了新舊兩個(gè)AOF文件的交替。這個(gè)信號(hào)處理函數(shù)執(zhí)行完畢之后,主進(jìn)程就可以繼續(xù)像往常一樣接受命令請(qǐng)求了
。在整個(gè)AOF后臺(tái)重寫過程中,只有最后的寫入緩存和改名操作會(huì)造成主進(jìn)程阻塞,在其他時(shí)候,AOF后臺(tái)重寫都不會(huì)對(duì)主進(jìn)程造成阻塞,這將AOF重寫對(duì)性能造成的影響降到了最低。
AOF重寫觸發(fā)方式
1、配置觸發(fā)
#表示當(dāng)前aof文件大小超過上一次aof文件大小的百分之多少的時(shí)候會(huì)進(jìn)行重寫。如果之前沒有重寫過,以啟動(dòng)時(shí)aof文件大小為準(zhǔn) auto-aof-rewrite-percentage 100 #限制允許重寫最小aof文件大小,也就是文件大小小于64mb的時(shí)候,不需要進(jìn)行優(yōu)化 auto-aof-rewrite-min-size 64mb
2、執(zhí)行bgrewriteaof命令
127.0.0.1:6379>bgrewriteaof‘ Backgroundappendonlyfilerewritingstarted
AOF重寫總結(jié)

混合持久化
RDB和AOF各有優(yōu)缺點(diǎn),Redis 4.0開始支持rdb和aof的混合持久化。
如果把混合持久化打開,aofrewrite的時(shí)候就直接把rdb的內(nèi)容寫到aof文件開頭。
RDB的頭+AOF的身體---->appendonly.aof
開啟混合持久化
aof-use-rdb-preambleyes
AOF文件的載入與數(shù)據(jù)還原
如果開啟了混合持久化,AOF在重寫時(shí),不再是單純將內(nèi)存數(shù)據(jù)轉(zhuǎn)換為RESP命令寫入AOF文件,而是將重寫這一刻之前的內(nèi)存做RDB快照處理,并且將RDB快照內(nèi)容和增量的AOF修改內(nèi)存數(shù)據(jù)的命令存在一起,都寫入新的AOF文件,新的文件一開始不叫appendonly.aof,等到重寫完新的AOF文件才會(huì)進(jìn)行改名,覆蓋原有的AOF文件,完成新舊兩個(gè)AOF文件的替換。
于是在Redis重啟的時(shí)候,可以先加載RDB的內(nèi)容,然后再重放增量AOF日志就可以完全替代之前的AOF全量文件重放,因此重啟效率大幅得到提升。
1、創(chuàng)建一個(gè)不帶網(wǎng)絡(luò)連接的偽客戶端(fake client)
因?yàn)镽edis的命令只能在客戶端上下文中執(zhí)行,而載入AOF文件時(shí)所使用的命令直接來源于AOF文件而不是網(wǎng)絡(luò)連接,所以服務(wù)器使用了一個(gè)沒有網(wǎng)絡(luò)連接的偽客戶端來執(zhí)行AOF文件保存的寫命令,偽客戶端執(zhí)行命令的效果和帶網(wǎng)絡(luò)連接的客戶端執(zhí)行命令的效果完全一樣
2、從AOF文件中分析并讀取出一條寫命令
3、使用偽客戶端執(zhí)行被讀出的寫命令
4、一直執(zhí)行步驟2和步驟3,直到AOF文件中的所有寫命令都被處理完畢為止

Redis數(shù)據(jù)備份策略
1.寫crontab定時(shí)調(diào)度腳本,每小時(shí)都copy一份rdb或aof的備份到一個(gè)目錄中去,僅僅保留最近48小時(shí)的備份
2.每天都保留一份當(dāng)日的數(shù)據(jù)備份到一個(gè)目錄中去,可以保留最近1個(gè)月的備份
3.每次copy備份的時(shí)候,都把太舊的備份給刪了
4.每天晚上將當(dāng)前機(jī)器上的備份復(fù)制一份到其他機(jī)器上,以防機(jī)器損壞
RDB和AOF對(duì)比
1、RDB存某個(gè)時(shí)刻的數(shù)據(jù)快照,采用二進(jìn)制壓縮存儲(chǔ),AOF存操作命令,采用文本存儲(chǔ)(混合)
2、RDB性能高、AOF性能較低
3、RDB在配置觸發(fā)狀態(tài)會(huì)丟失最后一次快照以后更改的所有數(shù)據(jù),AOF設(shè)置為每秒保存一次,則最多丟2秒的數(shù)據(jù)
4、Redis以主服務(wù)器模式運(yùn)行,RDB不會(huì)保存過期鍵值對(duì)數(shù)據(jù),Redis以從服務(wù)器模式運(yùn)行,RDB會(huì)保存過期鍵值對(duì),當(dāng)主服務(wù)器向從服務(wù)器同步時(shí),再清空過期鍵值對(duì)。AOF寫入文件時(shí),對(duì)過期的key會(huì)追加一條del命令,當(dāng)執(zhí)行AOF重寫時(shí),會(huì)忽略過期key和del命令。
看完了這篇文章,相信你對(duì)“Redis中持久化機(jī)制是怎么樣的”有了一定的了解,如果想了解更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!
新聞名稱:Redis中持久化機(jī)制是怎么樣的
當(dāng)前路徑:http://chinadenli.net/article20/jgjcco.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站建設(shè)、微信小程序、做網(wǎng)站、手機(jī)網(wǎng)站建設(shè)、動(dòng)態(tài)網(wǎng)站、企業(yè)網(wǎng)站制作
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)