Redis持久化解讀
Redis 是內(nèi)存級(jí)數(shù)據(jù)庫(kù),其數(shù)據(jù)存儲(chǔ)在內(nèi)存中,因此能夠提供快速的讀寫(xiě)速度。但我們知道內(nèi)存屬于掉電易失存儲(chǔ)器,一旦斷電,存儲(chǔ)在內(nèi)存中的數(shù)據(jù)就會(huì)丟失。
在服務(wù)器重啟和 Redis 服務(wù)重啟后數(shù)據(jù)都會(huì)丟失。因此 Redis 提供了三種持久化方式:RDB(快照持久化),AOF(追加文件持久化),混合持久化(混合使用 AOF 日志和內(nèi)存快照)。其中AOF 文件的內(nèi)容是操作命令,RDB 文件的內(nèi)容是二進(jìn)制數(shù)據(jù)。
RDB快照
RDB快照是一種將Redis數(shù)據(jù)庫(kù)狀態(tài)保存到磁盤(pán)上的機(jī)制,Redis提供了兩個(gè)命令:save , bgsave。
這兩個(gè)命令實(shí)際上都會(huì)生成一份RDB文件,RDB存儲(chǔ)了執(zhí)行命令時(shí)的 Redis 的所有數(shù)據(jù),在 Redis 啟動(dòng)時(shí),會(huì)自動(dòng)加載RDB文件恢復(fù)數(shù)據(jù)。Redis并沒(méi)有手動(dòng)加載RDB文件的命令。
save與bgsave
save 命令是在主線(xiàn)程下執(zhí)行,由于和執(zhí)行操作命令在同一個(gè)線(xiàn)程,所以如果寫(xiě)入 RDB 文件的時(shí)間太長(zhǎng),會(huì)阻塞主線(xiàn)程。
bgsave 命令會(huì)創(chuàng)建一個(gè)子進(jìn)程執(zhí)行 save 命令,主進(jìn)程不會(huì)阻塞。
Redis可以通過(guò)配置文件的選項(xiàng)來(lái)實(shí)現(xiàn)每隔一段時(shí)間自動(dòng)執(zhí)行一次 bgsava 命令:
save <seconds> <changes>
- <seconds>:自上次保存后經(jīng)過(guò)的時(shí)間(以秒為單位)。
- <changes>:在這個(gè)時(shí)間段內(nèi)至少有多少個(gè)鍵被改變。
使用示例: 上次快照以來(lái)有 60 秒并且至少有 1000 個(gè)鍵被改變,則自動(dòng)執(zhí)行 bgsave。
save 60 1000
我們可以設(shè)置多個(gè) save ,只要有一個(gè)條件滿(mǎn)足就會(huì)執(zhí)行 bgsave。
save 900 1 save 300 10 save 60 10000
bgsave 會(huì)先 fork 創(chuàng)建出子進(jìn)程,在 Linux 中 fork 創(chuàng)建出的子進(jìn)程會(huì)復(fù)制父進(jìn)程的頁(yè)表,與父進(jìn)程共享一份物理內(nèi)存。
這種方式減少了創(chuàng)建子進(jìn)程時(shí)的性能損耗,從而加快創(chuàng)建子進(jìn)程的速度,避免主進(jìn)程阻塞。創(chuàng)建子進(jìn)程后,子進(jìn)程只讀,同時(shí)將數(shù)據(jù)存儲(chǔ)在 RDB 文件中。
當(dāng)執(zhí)行命令的主線(xiàn)程內(nèi)存數(shù)據(jù)也都是只讀操作時(shí),主線(xiàn)程和 bgsave 子進(jìn)程相互不影響。當(dāng)主進(jìn)程對(duì)內(nèi)存數(shù)據(jù)修改時(shí)會(huì)觸發(fā)中斷,中斷處理程序會(huì)申請(qǐng)一份物理內(nèi)存重新映射到修改的虛擬內(nèi)存,這個(gè)過(guò)程叫做寫(xiě)時(shí)拷貝。
因此,當(dāng)主進(jìn)程執(zhí)行寫(xiě)操作時(shí),對(duì)數(shù)據(jù)的修改不會(huì)影響到子進(jìn)程,子進(jìn)程持久化的仍是執(zhí)行 fork 命令時(shí)刻的數(shù)據(jù)。 因此會(huì)產(chǎn)生數(shù)據(jù)丟失。
在極端情況下,如果所有的共享內(nèi)存都被修改,則此時(shí)的內(nèi)存占用是原先的 2 倍。所以,針對(duì)寫(xiě)操作多的場(chǎng)景,我們要留意下快照過(guò)程中內(nèi)存的變化,防止內(nèi)存被占滿(mǎn)了。
RDB優(yōu)缺點(diǎn)
RDB優(yōu)點(diǎn):
- 快速恢復(fù): RDB 文件是二進(jìn)制格式,可以非??焖俚丶虞d到內(nèi)存中,實(shí)現(xiàn)Redis服務(wù)的快速啟動(dòng)。
- 數(shù)據(jù)備份: RDB 文件可以很容易地被復(fù)制到其他服務(wù)器或備份存儲(chǔ)中,適合于進(jìn)行數(shù)據(jù)備份和災(zāi)難恢復(fù)。
- 空間緊湊: 由于RDB文件只包含最終的數(shù)據(jù),而不是每一條寫(xiě)命令,所以通常比AOF文件更緊湊。
- 減少I(mǎi)/O操作: 相比于A(yíng)OF持久化,RDB不需要記錄每一條寫(xiě)操作命令,因此減少了I/O操作。
- 適合大規(guī)模數(shù)據(jù)恢復(fù): 由于RDB文件包含了數(shù)據(jù)集的全量快照,適合于大規(guī)模數(shù)據(jù)的恢復(fù)。
RDB缺點(diǎn):
- 數(shù)據(jù)丟失風(fēng)險(xiǎn):如果兩次快照之間Redis發(fā)生故障,那么這段時(shí)間內(nèi)的數(shù)據(jù)將丟失。
- 數(shù)據(jù)完整性不高:RDB無(wú)法保證數(shù)據(jù)的完整性和一致性。
- 阻塞:盡管 bgsave 是在后臺(tái)異步執(zhí)行的,但在生成RDB文件時(shí),如果數(shù)據(jù)集非常大,仍然可能會(huì)短暫地阻塞主線(xiàn)程。
- 不適合高頻率寫(xiě)操作的場(chǎng)景:在寫(xiě)操作非常頻繁的場(chǎng)景,會(huì)頻繁生成RDB快照對(duì)性能產(chǎn)生影響。
AOF日志
AOF日志持久化并不是直接保存 Redis 中的數(shù)據(jù),而是記錄Redis中執(zhí)行的所有寫(xiě)操作命令。每當(dāng)Redis執(zhí)行一個(gè)寫(xiě)操作命令,該命令會(huì)被追加到AOF文件中。
在 Redis 中 AOF 持久化功能默認(rèn)是不開(kāi)啟的,需要我們修改 Redis.conf 配置文件中的以下參數(shù)
- appendonly yes:開(kāi)啟AOF持久化。
- appendfilename "appendonly.aof":指定AOF文件的名稱(chēng)。
Redis 會(huì)先執(zhí)行命令,執(zhí)行命令成功后再將命令記錄到 AOF 日志中,如果先寫(xiě)入 AOF 文件還需要檢查命令是否執(zhí)行成功,如果命令執(zhí)行失敗還需要額外操作。先執(zhí)行命令也保證了AOF 不會(huì)阻塞當(dāng)前寫(xiě)操作命令的執(zhí)行(但可能會(huì)阻塞下一個(gè)命令的執(zhí)行),因?yàn)楫?dāng)寫(xiě)操作命令執(zhí)行成功后,才會(huì)將命令記錄到 AOF 日志。
AOF持久化,會(huì)先將命令寫(xiě)入內(nèi)存緩沖區(qū)中。這個(gè)內(nèi)存緩沖區(qū)稱(chēng)為 AOF 緩沖區(qū)。然后再通過(guò) wirte系統(tǒng)調(diào)用寫(xiě)入到磁盤(pán)上的 AOF 文件。但 wirte寫(xiě)入實(shí)際上是將數(shù)據(jù)拷貝到內(nèi)核緩存區(qū),由內(nèi)核決定何時(shí)進(jìn)行磁盤(pán)IO。如果系統(tǒng)宕機(jī),而緩沖區(qū)數(shù)據(jù)沒(méi)有寫(xiě)入磁盤(pán),這部分?jǐn)?shù)據(jù)就會(huì)丟失。
AOF寫(xiě)回策略
Redis可以通過(guò)fsync或fdatasync系統(tǒng)調(diào)用來(lái)請(qǐng)求操作系統(tǒng)將內(nèi)核緩存區(qū)中的數(shù)據(jù)強(qiáng)制刷新到磁盤(pán)上。
AOF提供了三種寫(xiě)回策略: always ,everysec , no。
- always:每次寫(xiě)操作命令執(zhí)行完后,同步將 AOF 日志數(shù)據(jù)寫(xiě)回硬盤(pán)。即每次執(zhí)行后都調(diào)用 fsync。
- everysec :每次寫(xiě)操作命令執(zhí)行完后,先將命令寫(xiě)入到 AOF 文件的內(nèi)核緩沖區(qū),然后每隔一秒將緩沖區(qū)里的內(nèi)容寫(xiě)回到硬盤(pán),即每秒執(zhí)行一次 fsync 。
- no: 不由 Redis 控制寫(xiě)回硬盤(pán)的時(shí)機(jī),轉(zhuǎn)交給操作系統(tǒng)控制寫(xiě)回的時(shí)機(jī),也就是每次寫(xiě)操作命令執(zhí)行完后,先將命令寫(xiě)入到 AOF 文件的內(nèi)核緩沖區(qū),再由操作系統(tǒng)決定何時(shí)將緩沖區(qū)內(nèi)容寫(xiě)回硬盤(pán)。即不執(zhí)行 fsync 。
這三種策略各有優(yōu)缺點(diǎn), always 可靠性最強(qiáng)性能較差,no 性能最強(qiáng)可靠性最差,everysec則更為折中。大家可以根據(jù)自己的需要選擇策略。
AOF重寫(xiě)
AOF日志是一個(gè)文件,隨著執(zhí)行的寫(xiě)操作命令越來(lái)越多,文件的大小會(huì)越來(lái)越大。如果 AOF 文件過(guò)大必然會(huì)影響性能。因此 Redis 提供了 AOF重寫(xiě)機(jī)制。
當(dāng) AOF 文件的大小達(dá)到一定閾值時(shí),Redis 會(huì)觸發(fā) AOF 重寫(xiě)過(guò)程。這個(gè)閾值可以通過(guò)配置設(shè)置。
auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb
- auto-aof-rewrite-percentage:指定 AOF 文件大小相對(duì)于上一次重寫(xiě)后大小的增長(zhǎng)百分比,當(dāng)超過(guò)這個(gè)百分比時(shí),Redis 將觸發(fā) AOF 重寫(xiě)。
- auto-aof-rewrite-min-size: 這個(gè)配置項(xiàng)指定了 AOF 文件的最小大小,只有當(dāng) AOF 文件的大小超過(guò)這個(gè)值時(shí),auto-aof-rewrite-percentage 指定的百分比閾值才會(huì)生效。
什么是重寫(xiě)?AOF 文件記錄了每一個(gè)寫(xiě)操作命令,如果記錄了對(duì)同一數(shù)據(jù)的多個(gè)操作,實(shí)際上只有最后一個(gè)操作是有意義的,其他操作都是冗余的。AOF 重寫(xiě)機(jī)制通過(guò)創(chuàng)建一個(gè)新的 AOF 文件來(lái)解決這個(gè)問(wèn)題,新文件只包含恢復(fù)當(dāng)前數(shù)據(jù)集所需的最小命令集合。
在重寫(xiě)時(shí) Redis 會(huì)通過(guò) fork() 系統(tǒng)調(diào)用創(chuàng)建一個(gè)子進(jìn)程,這個(gè)子進(jìn)程與父進(jìn)程共享相同的內(nèi)存空間。子進(jìn)程會(huì)遍歷 Redis 數(shù)據(jù)庫(kù)中的所有鍵,并生成一系列可以恢復(fù)這些數(shù)據(jù)的 Redis 命令,同時(shí)將這些命令寫(xiě)入到一個(gè)臨時(shí)的 AOF 文件中。
重寫(xiě)完成后,子進(jìn)程會(huì)用新的 AOF 文件替換舊的 AOF 文件,并更新 AOF 文件的文件名。
在重寫(xiě)過(guò)程中,主進(jìn)程并不會(huì)阻塞而是繼續(xù)處理客戶(hù)端請(qǐng)求,同時(shí)將執(zhí)行后的寫(xiě)命令追加到 「AOF 緩沖區(qū)」與「AOF 重寫(xiě)緩沖區(qū)」。
當(dāng)重寫(xiě)完成時(shí),會(huì)向主進(jìn)程發(fā)送一條信號(hào),主進(jìn)程收到該信號(hào)后,會(huì)調(diào)用一個(gè)信號(hào)處理函數(shù),該函數(shù)會(huì)做以下工作:
- 將 AOF 重寫(xiě)緩沖區(qū)中的所有內(nèi)容追加到新的 AOF 的文件中。
- 新的 AOF 的文件進(jìn)行改名,覆蓋現(xiàn)有的 AOF 文件。
然后主進(jìn)程會(huì)繼續(xù)接收命令并執(zhí)行,重寫(xiě)也就此完成。
AOF優(yōu)缺點(diǎn)
AOF優(yōu)點(diǎn):
- 數(shù)據(jù)安全性高: AOF 記錄了所有寫(xiě)操作,可以提供更好的數(shù)據(jù)恢復(fù)保證。
- 數(shù)據(jù)完整性: AOF 能夠保證即使在 Redis 異常終止的情況下,也不會(huì)丟失任何已持久化的寫(xiě)操作。
AOF缺點(diǎn):
- 磁盤(pán)空間使用: AOF 文件可能會(huì)比 RDB 文件大,因?yàn)樗涗浟怂械膶?xiě)操作命令。
- 性能影響: 頻繁的磁盤(pán)I/O操作可能會(huì)影響 Redis 的性能。
- 數(shù)據(jù)恢復(fù)速度: 由于 AOF 文件可能包含大量的命令,數(shù)據(jù)恢復(fù)速度會(huì)比 RDB 慢。
混合持久化
我們可以看到RDB與AOF各有優(yōu)缺點(diǎn):RDB 恢復(fù)速度快,AOF 丟失數(shù)據(jù)少?Redis 4.0 引入了一種新的持久化方式,稱(chēng)為混合持久化,它結(jié)合了 RDB和 AOF持久化的優(yōu)點(diǎn)。
我們可以通過(guò)配置文件開(kāi)啟混合持久化:
aof-use-rdb-preamble yes
當(dāng)開(kāi)啟了混合持久化時(shí),在 AOF 重寫(xiě)時(shí),重寫(xiě)子進(jìn)程會(huì)先將與主線(xiàn)程共享的內(nèi)存數(shù)據(jù)以 RDB 方式寫(xiě)入到 AOF 文件,然后主線(xiàn)程處理的操作命令會(huì)被記錄在重寫(xiě)緩沖區(qū)里,重寫(xiě)緩沖區(qū)里的增量命令會(huì)以 AOF 方式寫(xiě)入到 AOF 文件,寫(xiě)入完成后通知主進(jìn)程將新的含有 RDB 格式和 AOF 格式的 AOF 文件替換舊的的 AOF 文件。
當(dāng) Redis 重啟時(shí),它會(huì)首先加載 RDB 文件快速恢復(fù)數(shù)據(jù)狀態(tài)。 然后,Redis 會(huì)執(zhí)行保存在 AOF 文件中的寫(xiě)操作命令(這里的內(nèi)容是 Redis 后臺(tái)子進(jìn)程重寫(xiě) AOF 期間,主線(xiàn)程處理的操作命令。),恢復(fù)到最新的數(shù)據(jù)狀態(tài)。
混合持久化的主要優(yōu)點(diǎn)是結(jié)合了 RDB 和 AOF 的優(yōu)點(diǎn),提供了更快的數(shù)據(jù)恢復(fù)速度和更少的數(shù)據(jù)丟失風(fēng)險(xiǎn)。在 AOF 重寫(xiě)過(guò)程中,Redis 確保了數(shù)據(jù)的完整性和一致性,同時(shí)優(yōu)化了磁盤(pán)空間的使用。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Redis數(shù)據(jù)過(guò)期策略的實(shí)現(xiàn)詳解
最近項(xiàng)目當(dāng)中遇到一個(gè)需求場(chǎng)景,需要清空一些存放在Redis的數(shù)據(jù),本文對(duì)Redis的過(guò)期機(jī)制簡(jiǎn)單的講解一下,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09Redis shake實(shí)現(xiàn)可視化監(jiān)控的示例代碼
Redis可視化監(jiān)控是通過(guò)監(jiān)控Redis服務(wù)器的各項(xiàng)指標(biāo)和狀態(tài),并將其以可視化的方式展示給用戶(hù),本文給大家介紹了Redis shake實(shí)現(xiàn)可視化監(jiān)控,并通過(guò)代碼示例講解的非常詳細(xì),需要的朋友可以參考下2024-03-03Redis數(shù)據(jù)導(dǎo)入導(dǎo)出以及數(shù)據(jù)遷移的4種方法詳解
這篇文章主要介紹了Redis數(shù)據(jù)導(dǎo)入導(dǎo)出以及數(shù)據(jù)遷移的4種方法詳解,需要的朋友可以參考下2020-02-02NestJS+Redis實(shí)現(xiàn)手寫(xiě)一個(gè)限流器
限流是大型系統(tǒng)必備的保護(hù)措施,本文將結(jié)合redis , lua 腳本 以及 Nestjs Guard 來(lái)實(shí)現(xiàn) 限流的效果,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-11-11關(guān)于分布式鎖的三種實(shí)現(xiàn)方式
這篇文章主要介紹了關(guān)于分布式鎖的三種實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08基于session?Redis實(shí)現(xiàn)登錄
這篇文章主要介紹了基于session?Redis實(shí)現(xiàn)登錄的相關(guān)資料,需要的朋友可以參考下2023-10-10