溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Redis 持久化和過(guò)期機(jī)制

發(fā)布時(shí)間:2020-08-03 16:04:15 來(lái)源:網(wǎng)絡(luò) 閱讀:384 作者:Java_老男孩 欄目:編程語(yǔ)言

本文主要介紹了 Redis 持久化的兩種機(jī)制:RDB 和 AOF,以及鍵過(guò)期的策略:惰性刪除和定期刪除,還有 RDB、AOF 和復(fù)制功能對(duì)過(guò)期鍵的處理。

RDB

RDB 是 Redis 持久化的第一種方式。有兩個(gè) Redis 命令可以用于生成 RDB 文件,一個(gè)是 SAVE,另一個(gè)是 BGSAVE。
SAVE 會(huì)阻塞 Redis 服務(wù)器進(jìn)程,執(zhí)行時(shí) Redis 服務(wù)器會(huì)阻塞所有客戶端發(fā)送的命令。

redis> SAVE
OK

BGSAVE 會(huì)派生出一個(gè)子進(jìn)程執(zhí)行,執(zhí)行時(shí)仍可繼續(xù)處理客戶端的命令,但會(huì)拒絕客戶端 SAVE 和 BGSAVE 的命令,延遲 BGREWRITEAOF 命令。

redis> BGSAVE
Background saving started

執(zhí)行條件

SAVE 命令會(huì)阻塞服務(wù)器,所以只能手動(dòng)執(zhí)行。BGSAVE 可以在不阻塞的情況下執(zhí)行,所以可以配置 save 選項(xiàng)讓服務(wù)器每隔一段時(shí)間自動(dòng)執(zhí)行一次。

比如我們可以向服務(wù)器提供以下配置:

save  900  1
save  300  10
save  60  10000

那么只要滿足以下三個(gè)條件中的任意一個(gè)即可被執(zhí)行:

  • 服務(wù)器在 900 秒之內(nèi)對(duì)數(shù)據(jù)庫(kù)進(jìn)行了至少 1 次修改。
  • 服務(wù)器在 300 秒之內(nèi)對(duì)數(shù)據(jù)庫(kù)進(jìn)行了至少 10 次修改。
  • 服務(wù)器在 60 秒之內(nèi)對(duì)數(shù)據(jù)庫(kù)進(jìn)行了至少 10000 次修改。

為了實(shí)現(xiàn)這一功能,服務(wù)器會(huì)維持一個(gè)記錄距離上次保存之后修改的次數(shù)的 dirty 計(jì)數(shù)器和一個(gè)記錄上次保存時(shí)間的 lastsave 屬性。

周期操作函數(shù) serverCron 默認(rèn)每個(gè) 100 毫秒就會(huì)執(zhí)行一次,它的其中一項(xiàng)工作就是檢查 save 選項(xiàng)設(shè)置的條件是否滿足,如果滿足的話就會(huì)執(zhí)行 BGSAVE 命令。

文件內(nèi)容

RDB 文件有多個(gè)部分,包括握手字段 ‘REDIS’ 字符串,版本號(hào),數(shù)據(jù)庫(kù),’EOF’ 和校驗(yàn)字段。

核心部分是數(shù)據(jù)庫(kù)字段,數(shù)據(jù)庫(kù)字段包括了握手字段 ‘SELECTDB’,數(shù)據(jù)庫(kù)編號(hào)和鍵值對(duì),數(shù)據(jù)庫(kù)編號(hào)指示了這是第幾個(gè)數(shù)據(jù)庫(kù),而鍵值對(duì)則保存了各項(xiàng)數(shù)據(jù)。

鍵值對(duì)中除了類型和數(shù)據(jù),還可能會(huì)有過(guò)期時(shí)間。對(duì)于不同類型的鍵值對(duì),RDB 文件會(huì)用不同的方式來(lái)保存它們。

RDB 文件本身是一個(gè)經(jīng)過(guò)壓縮的二進(jìn)制文件,每次 SAVE 或者 BGSAVE 都會(huì)創(chuàng)建一個(gè)新的 RDB 文件,不支持追加操作。

AOF

AOF 是 Redis 持久化的第二種方式,在 AOF 和 RDB 同時(shí)開(kāi)啟時(shí),服務(wù)器會(huì)優(yōu)先考慮從 AOF 恢復(fù)數(shù)據(jù),因?yàn)?AOF 每次記錄間隔的時(shí)間更短。

和 RDB 直接記錄鍵值對(duì)不同,AOF 記錄的是命令。服務(wù)器在執(zhí)行完一個(gè)寫(xiě)命令以后,會(huì)把這條命令追加到服務(wù)器 aof_buf 緩沖區(qū)的末尾,并在一個(gè)適當(dāng)?shù)臅r(shí)候?qū)懭胛募V亟〞r(shí)服務(wù)器會(huì)創(chuàng)建一個(gè)偽客戶端,依次執(zhí)行文件中的命令即可完成數(shù)據(jù)的載入。

文件的寫(xiě)入與同步

AOF 的持久化發(fā)生在每次事件循環(huán)結(jié)束之前,會(huì)阻塞服務(wù)器。在持久化時(shí)會(huì)調(diào)用操作系統(tǒng)的 write 函數(shù),但通常該函數(shù)會(huì)把數(shù)據(jù)保存在一個(gè)內(nèi)存緩沖區(qū)里面而不是立刻刷入磁盤(pán)。這就帶來(lái)一個(gè)安全問(wèn)題。為了避免這個(gè)問(wèn)題操作系統(tǒng)又提供了 fsync 和 fdatasync 兩個(gè)強(qiáng)制刷盤(pán)的同步函數(shù)。我們把 write 稱為寫(xiě)入,把 fsync 和 fdatasync 稱為同步。

服務(wù)器會(huì)在每次事件循環(huán)結(jié)束之前根據(jù) appendfsync 選項(xiàng)寫(xiě)入和同步 aof_buf 中的數(shù)據(jù):

  • always:寫(xiě)入并同步
  • everysec:寫(xiě)入,如果距離上次同步超過(guò) 1 秒,則同步
  • no:只寫(xiě)入,何時(shí)同步由操作系統(tǒng)決定

AOF 重寫(xiě)

隨著服務(wù)器運(yùn)行時(shí)間的流逝,AOF 文件中的內(nèi)容會(huì)越來(lái)越多,文件的體積也會(huì)越來(lái)越大,不僅會(huì)對(duì)宿主計(jì)算機(jī)造成影響,也拖慢了數(shù)據(jù)恢復(fù)所需要的時(shí)間。

AOF 重寫(xiě)是指重新生成一個(gè) AOF 文件替換原來(lái)的 AOF 文件。但這里的重寫(xiě)不會(huì)對(duì)原有的文件進(jìn)行讀取、分析或者寫(xiě)入,而是把數(shù)據(jù)庫(kù)中的鍵值對(duì)折算成命令,重新寫(xiě)入新的文件。

重寫(xiě)是一個(gè)耗時(shí)的操作,因此 Redis 把它放到后臺(tái)去操作,對(duì)應(yīng)的指令是 BGREWRITEAOF。在重寫(xiě)過(guò)程中服務(wù)器還可能接收新的指令,因此 Redis 會(huì)維護(hù)一個(gè) AOF 重寫(xiě)緩沖區(qū),記錄重寫(xiě)期間的寫(xiě)命令,在重寫(xiě)完成后追加到 AOF 文件末尾。

RDB 和 AOF 對(duì)比

RDB 的優(yōu)點(diǎn)

  • RDB 是一個(gè)非常緊湊的文件,它的體積更小,且可以選擇持久化的時(shí)間,適合做備份的文件。比如每天的備份,每月的備份。
  • RDB 對(duì)主進(jìn)程更友好,父進(jìn)程只需要 fork 出一個(gè)子進(jìn)程,無(wú)須執(zhí)行任何磁盤(pán) I/O 操作。
  • RDB 在恢復(fù)大數(shù)據(jù)集時(shí)的速度比 AOF 的恢復(fù)速度要快。

RDB 的缺點(diǎn)

  • 因?yàn)?RDB 文件需要保存整個(gè)數(shù)據(jù)集的狀態(tài), 所以它并不是一個(gè)輕松的操作。 因此你可能會(huì)至少 5 分鐘才保存一次 RDB 文件,間隔時(shí)間比較長(zhǎng)。
  • RDB 雖然會(huì)把持久化的操作交給子進(jìn)程,但每次都會(huì)從頭開(kāi)始,在數(shù)據(jù)集比較龐大時(shí), fork() 可能會(huì)非常耗時(shí),造成服務(wù)器在某某毫秒內(nèi)停止處理客戶端; 如果數(shù)據(jù)集非常巨大,并且 CPU 時(shí)間非常緊張的話,那么這種停止時(shí)間甚至可能會(huì)長(zhǎng)達(dá)整整一秒。

AOF 的優(yōu)點(diǎn)

  • AOF 使用追加的方式,每次寫(xiě)入時(shí)間很短,因此可以允許更短間隔的持久化操作,比如 1 秒。
  • AOF 文件的可讀性比較好,如果你不小心執(zhí)行了一條命令,只要 AOF 文件未被重寫(xiě),那么只要停止服務(wù)器,移除 AOF 文件里的該條命令然后重啟 Redis 即可。

AOF 的缺點(diǎn)

  • 對(duì)于相同的數(shù)據(jù)集來(lái)說(shuō),AOF 文件的體積通常要大于 RDB 文件的體積。
  • 使用 fsync 會(huì)降低 Redis 的性能,導(dǎo)致 AOF 的速度可能會(huì)慢于 RDB 。

RDB 和 AOF 各有所長(zhǎng),RDB 體積小,恢復(fù)速度快,而且可以生成快照;AOF 頻率更高,可以保存更新的數(shù)據(jù)。一般來(lái)說(shuō),推薦同時(shí)使用。

Redis 過(guò)期機(jī)制

Redis 采取的是惰性刪除和定期刪除配合使用的方式。

惰性刪除是指 Redis 會(huì)在訪問(wèn)某個(gè)鍵的時(shí)候檢查該鍵是否過(guò)期,如果過(guò)期,就會(huì)將輸入鍵從數(shù)據(jù)庫(kù)中刪除。但惰性刪除不能及時(shí)清理內(nèi)存,因此 Redis 還有定期刪除的機(jī)制。

定期刪除是另一種過(guò)期鍵刪除方式。Redis 會(huì)維護(hù)一個(gè)過(guò)期字典(如下圖所示),所有聲明了過(guò)期時(shí)間的鍵都會(huì)被添加進(jìn)這個(gè)字典中。周期操作函數(shù) serverCron 執(zhí)行時(shí),會(huì)在規(guī)定時(shí)間內(nèi)隨機(jī)檢查一部分鍵的過(guò)期時(shí)間,并刪除其中的過(guò)期鍵。

Redis 持久化和過(guò)期機(jī)制

RDB、AOF 和復(fù)制功能對(duì)過(guò)期鍵的處理

RDB 對(duì)過(guò)期鍵的處理

RDB 文件在生成時(shí)會(huì)檢查每個(gè)鍵的過(guò)期時(shí)間,過(guò)期鍵不會(huì)被添加進(jìn) RDB 文件里。

載入 RDB 文件時(shí),如果該服務(wù)器是主服務(wù)器,則不會(huì)載入文件中過(guò)期的鍵;如果該服務(wù)器是從服務(wù)器,則不論過(guò)期與否都會(huì)被載入。不過(guò),因?yàn)橹鲝姆?wù)器在同步的時(shí)候,從服務(wù)器的數(shù)據(jù)庫(kù)會(huì)被清空,所以一般來(lái)講,過(guò)期鍵對(duì)載入 RDB 文件的從服務(wù)器不會(huì)造成影響。

AOF 對(duì)過(guò)期鍵的處理

AOF 文件寫(xiě)入時(shí),如果數(shù)據(jù)庫(kù)中的某個(gè)鍵已過(guò)期,但它還沒(méi)被刪除,那么 AOF 文件不會(huì)因?yàn)檫@個(gè)鍵產(chǎn)生任何影響。當(dāng)它被惰性刪除或者定期刪除之后,程序會(huì)向 AOF 文件追加一條 DEL 命令顯示記錄該鍵已被刪除。

AOF 重寫(xiě)時(shí),和生成 RDB 文件一樣,會(huì)過(guò)濾掉已經(jīng)過(guò)期的鍵。

復(fù)制功能對(duì)過(guò)期鍵的處理

主服務(wù)器在刪除一個(gè)過(guò)期鍵后,會(huì)顯式地向所有從服務(wù)器發(fā)送一個(gè) DEL 命令,告知從服務(wù)器刪除這個(gè)過(guò)期鍵。

Redis 3.2 前,為了保持主從一致性,從服務(wù)器在執(zhí)行客戶端發(fā)送的讀命令時(shí),即使碰到過(guò)期鍵也不會(huì)將過(guò)期鍵刪除,而是繼續(xù)像處理未過(guò)期鍵一樣處理過(guò)期鍵。從服務(wù)器只有在接到主服務(wù)器發(fā)來(lái)的 DEL 命令之后,才會(huì)刪除過(guò)期鍵。Redis 3.2 后,從節(jié)點(diǎn)在讀取數(shù)據(jù)時(shí),增加了對(duì)數(shù)據(jù)是否過(guò)期的判斷:如果該數(shù)據(jù)已過(guò)期,則不返回給客戶端。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI