概述
redis跟memcached類似,都是內(nèi)存數(shù)據(jù)庫(kù),不過(guò)redis支持?jǐn)?shù)據(jù)持久化,也就是說(shuō)redis可以將內(nèi)存中的數(shù)據(jù)同步到磁盤來(lái)持久化,以確保redis 的數(shù)據(jù)安全。不過(guò)持久化這塊可能比較容易產(chǎn)生誤解,下面聊聊這塊。
Redis持久化是如何工作的?
什么是持久化?簡(jiǎn)單來(lái)講就是將數(shù)據(jù)放到斷電后數(shù)據(jù)不會(huì)丟失的設(shè)備中,也就是我們通常理解的硬盤上。
1、數(shù)據(jù)庫(kù)寫操作的5個(gè)過(guò)程
首先我們來(lái)看一下數(shù)據(jù)庫(kù)在進(jìn)行寫操作時(shí)到底做了哪些事,主要有下面五個(gè)過(guò)程:
- 客戶端向服務(wù)端發(fā)送寫操作(數(shù)據(jù)在客戶端的內(nèi)存中)。
- 數(shù)據(jù)庫(kù)服務(wù)端接收到寫請(qǐng)求的數(shù)據(jù)(數(shù)據(jù)在服務(wù)端的內(nèi)存中)。
- 服務(wù)端調(diào)用write這個(gè)系統(tǒng)調(diào)用,將數(shù)據(jù)往磁盤上寫(數(shù)據(jù)在系統(tǒng)內(nèi)存的緩沖區(qū)中)。
- 操作系統(tǒng)將緩沖區(qū)中的數(shù)據(jù)轉(zhuǎn)移到磁盤控制器上(數(shù)據(jù)在磁盤緩存中)。
- 磁盤控制器將數(shù)據(jù)寫到磁盤的物理介質(zhì)中(數(shù)據(jù)真正落到磁盤上)。
2、故障分析
寫操作大致有上面5個(gè)流程,當(dāng)數(shù)據(jù)庫(kù)系統(tǒng)故障時(shí),這時(shí)候系統(tǒng)內(nèi)核還是完好的。那么此時(shí)只要我們執(zhí)行完了第3步,那么數(shù)據(jù)就是安全的,因?yàn)楹罄m(xù)操作系統(tǒng)會(huì)來(lái)完成后面幾步,保證數(shù)據(jù)最終會(huì)落到磁盤上。當(dāng)系統(tǒng)斷電時(shí),這時(shí)候上面5項(xiàng)中提到的所有緩存都會(huì)失效,并且數(shù)據(jù)庫(kù)和操作系統(tǒng)都會(huì)停止工作。所以只有當(dāng)數(shù)據(jù)在完成第5步后,才能保證在斷電后數(shù)據(jù)不丟失。
【補(bǔ)充】這里可能有幾個(gè)疑問(wèn):
- 數(shù)據(jù)庫(kù)多長(zhǎng)時(shí)間調(diào)用一次write,將數(shù)據(jù)寫到內(nèi)核緩沖區(qū)?
- 內(nèi)核多長(zhǎng)時(shí)間會(huì)將系統(tǒng)緩沖區(qū)中的數(shù)據(jù)寫到磁盤控制器?
- 磁盤控制器又在什么時(shí)候把緩存中的數(shù)據(jù)寫到物理介質(zhì)上?
對(duì)于第一個(gè)問(wèn)題,通常數(shù)據(jù)庫(kù)層面會(huì)進(jìn)行全面控制。
而對(duì)第二個(gè)問(wèn)題,操作系統(tǒng)有其默認(rèn)的策略,但是我們也可以通過(guò)POSIX API提供的fsync系列命令強(qiáng)制操作系統(tǒng)將數(shù)據(jù)從內(nèi)核區(qū)寫到磁盤控制器上。
對(duì)于第三個(gè)問(wèn)題,看起來(lái)數(shù)據(jù)庫(kù)已經(jīng)無(wú)法觸及,但實(shí)際上,大多數(shù)情況下磁盤緩存是被設(shè)置關(guān)閉的,或者是只開啟為讀緩存,也就是說(shuō)寫操作不會(huì)進(jìn)行緩存,直接寫到磁盤。建議的做法是僅僅當(dāng)你的磁盤設(shè)備有備用電池時(shí)才開啟寫緩存。
3、數(shù)據(jù)損壞
所謂數(shù)據(jù)損壞,就是數(shù)據(jù)無(wú)法恢復(fù),上面我們講的都是如何保證數(shù)據(jù)是確實(shí)寫到磁盤上去,但是寫到磁盤上可能并不意味著數(shù)據(jù)不會(huì)損壞。比如我們可能一次寫請(qǐng)求會(huì)進(jìn)行兩次不同的寫操作,當(dāng)意外發(fā)生時(shí),可能會(huì)導(dǎo)致一次寫操作安全完成,但是另一次還沒有進(jìn)行。如果數(shù)據(jù)庫(kù)的數(shù)據(jù)文件結(jié)構(gòu)組織不合理,可能就會(huì)導(dǎo)致數(shù)據(jù)完全不能恢復(fù)的狀況出現(xiàn)。
三種解決策略:
1)最粗糙的處理,就是不通過(guò)數(shù)據(jù)的組織形式保證數(shù)據(jù)的可恢復(fù)性。而是通過(guò)配置數(shù)據(jù)同步備份的方式,在數(shù)據(jù)文件損壞后通過(guò)數(shù)據(jù)備份來(lái)進(jìn)行恢復(fù)。實(shí)際上MongoDB在不開啟操作日志,通過(guò)配置Replica Sets時(shí)就是這種情況。
2)在上面基礎(chǔ)上添加一個(gè)操作日志,每次操作時(shí)記一下操作的行為,這樣我們可以通過(guò)操作日志來(lái)進(jìn)行數(shù)據(jù)恢復(fù)。因?yàn)椴僮魅罩臼琼樞蜃芳拥姆绞綄懙模圆粫?huì)出現(xiàn)操作日志也無(wú)法恢復(fù)的情況。這也類似于MongoDB開啟了操作日志的情況。
3)更保險(xiǎn)的做法是數(shù)據(jù)庫(kù)不進(jìn)行舊數(shù)據(jù)的修改,只是以追加方式去完成寫操作,這樣數(shù)據(jù)本身就是一份日志,這樣就永遠(yuǎn)不會(huì)出現(xiàn)數(shù)據(jù)無(wú)法恢復(fù)的情況了。實(shí)際上CouchDB就是此做法的優(yōu)秀范例。
那么,redis又針對(duì)持久化提供了什么方式呢?
redis持久化的兩種方式
redis提供了兩種持久化的方式,分別是RDB(Redis DataBase)和AOF(Append Only File)。
RDB,簡(jiǎn)而言之,就是將存儲(chǔ)的數(shù)據(jù)快照的方式存儲(chǔ)到磁盤上,
AOF,則是將redis執(zhí)行過(guò)的所有寫指令記錄下來(lái),通過(guò)write函數(shù)追加到AOF文件的末尾。在下次redis重新啟動(dòng)時(shí),只要把這些寫指令從前到后再重復(fù)執(zhí)行一遍,就可以實(shí)現(xiàn)數(shù)據(jù)恢復(fù)了。
RDB機(jī)制
1、概念
RDB持久化是指在指定的時(shí)間間隔內(nèi)將內(nèi)存中的數(shù)據(jù)集快照寫入磁盤。也是默認(rèn)的持久化方式,這種方式是就是將內(nèi)存中數(shù)據(jù)以快照的方式寫入到二進(jìn)制文件中,默認(rèn)的文件名為dump.rdb。
