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 命令是在主線程下執(zhí)行,由于和執(zhí)行操作命令在同一個(gè)線程,所以如果寫(xiě)入 RDB 文件的時(shí)間太長(zhǎng),會(huì)阻塞主線程。
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è)條件滿足就會(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í)行命令的主線程內(nèi)存數(shù)據(jù)也都是只讀操作時(shí),主線程和 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)存被占滿了。
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操作: 相比于AOF持久化,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ě)操作的場(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文件的名稱。
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ū)稱為 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ù)處理客戶端請(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 引入了一種新的持久化方式,稱為混合持久化,它結(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ì)先將與主線程共享的內(nèi)存數(shù)據(jù)以 RDB 方式寫(xiě)入到 AOF 文件,然后主線程處理的操作命令會(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 期間,主線程處理的操作命令。),恢復(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高并發(fā)緩存架構(gòu)性能優(yōu)化實(shí)戰(zhàn)
本文主要介紹了淺談Redis高并發(fā)緩存架構(gòu)性能優(yōu)化實(shí)戰(zhàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05
odoo中使用redis實(shí)現(xiàn)緩存的步驟
這篇文章主要介紹了odoo中使用redis實(shí)現(xiàn)緩存的步驟,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-04-04
Redis異步隊(duì)列的實(shí)現(xiàn)及應(yīng)用場(chǎng)景
異步隊(duì)列是一種底層基于異步 I/O 模型的消息隊(duì)列,用于在分布式系統(tǒng)中進(jìn)行同步和異步的通訊和協(xié)作,本文主要介紹了Redis異步隊(duì)列的實(shí)現(xiàn)及應(yīng)用場(chǎng)景,感興趣的可以了解一下2023-12-12
Redis Lua腳本實(shí)現(xiàn)分布式鎖方式
文章主要介紹了在分布式系統(tǒng)中使用Lua腳本實(shí)現(xiàn)Redis分布式鎖的方法,包括可重入鎖的實(shí)現(xiàn)和注意事項(xiàng),以及紅鎖算法在Redis集群狀態(tài)下的潛在問(wèn)題2026-05-05
Redis事務(wù)機(jī)制與Springboot項(xiàng)目中的使用方式
Redis事務(wù)機(jī)制允許將多個(gè)命令打包在一起,作為一個(gè)原子操作來(lái)執(zhí)行,開(kāi)啟事務(wù)使用MULTI命令,執(zhí)行事務(wù)使用EXEC命令,取消事務(wù)使用DISCARD命令,監(jiān)視一個(gè)或多個(gè)鍵使用WATCH命令,Redis事務(wù)的核心思想是將多個(gè)命令放入一個(gè)隊(duì)列中2025-03-03
Redis 過(guò)期鍵刪除策略的實(shí)現(xiàn)示例

