自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Redis持久化:RDB和AOF

數(shù)據(jù)庫(kù) Redis
重啟 Redis 時(shí),我們很少使用 RDB 來(lái)恢復(fù)內(nèi)存狀態(tài),因?yàn)榭赡軄G失大量數(shù)據(jù)。通常采用 AOF 日志重放,但是重放 AOF 日志性能相對(duì) RDB 來(lái)說(shuō)要慢很多,在Redis實(shí)例很大的情況下,啟動(dòng)需要花費(fèi)很長(zhǎng)時(shí)間。

Redis 數(shù)據(jù)存儲(chǔ)在內(nèi)存中,如果不想辦法將數(shù)據(jù)保存到硬盤(pán)上,一旦Redis重啟(退出/故障),內(nèi)存的數(shù)據(jù)將會(huì)全部丟失。我們肯定不想 Redis 里的數(shù)據(jù)由于某些故障全部丟失(導(dǎo)致所有請(qǐng)求都走 MySQL),即便發(fā)生了故障也希望可以將Redis原有的數(shù)據(jù)恢復(fù)過(guò)來(lái),這就是持久化的作用。

Redis 提供了兩種不同的持久化方法來(lái)將數(shù)據(jù)存儲(chǔ)到硬盤(pán)里邊:

  • **RDB(Redis Database)**,將某一時(shí)刻的所有數(shù)據(jù)保存到一個(gè) RDB 文件中。
  • **AOF(append-only-file)**,當(dāng)Redis服務(wù)器執(zhí)行寫(xiě)命令的時(shí)候,將執(zhí)行的寫(xiě)命令保存到 AOF 文件中。

RDB內(nèi)存快照,讓宕機(jī)快速恢復(fù)

1.什么是RDB內(nèi)存快照?

在 Redis 執(zhí)行“寫(xiě)”指令的過(guò)程中,內(nèi)存數(shù)據(jù)一直會(huì)變化,所謂內(nèi)存快照,指的就是 Redis 內(nèi)存中數(shù)據(jù)在某一時(shí)刻的狀態(tài)數(shù)據(jù),好比時(shí)間定格在某一時(shí)刻。當(dāng)我們拍照時(shí),通過(guò)照片就能把某一時(shí)刻的瞬間畫(huà)面完全記錄下來(lái)。Redis 跟這個(gè)類(lèi)似,就是把某一刻的數(shù)據(jù)以文件的形式拍下來(lái),寫(xiě)到磁盤(pán)上,這個(gè)快照文件叫做 RDB 文件,RDB 就是 Redis Database 的縮寫(xiě)。

圖片


2.生成RDB的策略

Redis 并不會(huì)在每次執(zhí)行“寫(xiě)”指令的時(shí)候都觸發(fā) RDB 寫(xiě)磁盤(pán),只需要在執(zhí)行內(nèi)存快照的時(shí)候?qū)懘疟P(pán),這樣既保證了唯快不破,還實(shí)現(xiàn)了持久化,宕機(jī)快速恢復(fù)。

我們知道 Redis 的單線(xiàn)程模型決定了我們要盡可能地避免會(huì)阻塞主線(xiàn)程的操作,所以就需要盡可能地避免 RDB 文件生成阻塞主線(xiàn)程。為此Redis提供了兩個(gè)指令用于生成 RDB 文件:

  • SAVE:會(huì)阻塞 Redis 服務(wù)器進(jìn)程,服務(wù)器不能接收任何請(qǐng)求,直到 RDB 文件創(chuàng)建完畢為止。
  • BGSAVE:fork 出一個(gè)子進(jìn)程,由子進(jìn)程來(lái)負(fù)責(zé)創(chuàng)建 RDB 文件,服務(wù)器進(jìn)程可以繼續(xù)接收請(qǐng)求。

除了手動(dòng)調(diào)用 SAVE 或者 BGSAVE 命令生成 RDB 文件之外,我們可以使用配置的方式來(lái)定期執(zhí)行:在默認(rèn)的配置下,如果以下的條件被觸發(fā),就會(huì)執(zhí)行 BGSAVE 命令。

save 900 1              #在900秒(15分鐘)之后,至少有1個(gè)key發(fā)生變化,
save 300 10             #在300秒(5分鐘)之后,至少有10個(gè)key發(fā)生變化
save 60 10000           #在60秒(1分鐘)之后,至少有10000個(gè)key發(fā)生變化

3.RDB實(shí)現(xiàn)原理

在RDB執(zhí)行期間為了保證快照的數(shù)據(jù)一致性,只能處理讀操作,不能修改正在執(zhí)行快照的數(shù)據(jù),這種場(chǎng)景,Redis 是允許的。那 Redis 是如何實(shí)現(xiàn)一邊處理寫(xiě)請(qǐng)求,同時(shí)生成RDB文件的呢?

Redis 使用操作系統(tǒng)的多進(jìn)程寫(xiě)時(shí)復(fù)制技術(shù) COW(Copy On Write)來(lái)實(shí)現(xiàn)快照的持久化。

Redis 在持久化是會(huì)調(diào)用 glibc 的函數(shù)(linux系統(tǒng)中最底層的api)fork產(chǎn)生一個(gè)子進(jìn)程,快照持久化完全交給子進(jìn)程來(lái)處理,父進(jìn)程繼續(xù)處理客戶(hù)端請(qǐng)求。子進(jìn)程剛剛產(chǎn)生時(shí),它和父進(jìn)程共享內(nèi)存里面的代碼段和數(shù)據(jù)段,這時(shí)可以將父子進(jìn)程想象成一個(gè)連體嬰兒,共享身體。這是Linux操作系統(tǒng)的機(jī)制,為了節(jié)約內(nèi)存資源,所以盡可能讓它們共享起來(lái),在進(jìn)程分離的一瞬間,內(nèi)存的增長(zhǎng)幾乎沒(méi)有明顯的變化。

BGSAVE 子進(jìn)程可以共享主線(xiàn)程的所有內(nèi)存數(shù)據(jù),讀取主線(xiàn)程的數(shù)據(jù)并寫(xiě)入到 RDB 文件。當(dāng)主線(xiàn)程執(zhí)行寫(xiě)指令修改數(shù)據(jù)的時(shí)候,這個(gè)數(shù)據(jù)就會(huì)復(fù)制一份副本,BGSAVE 子進(jìn)程讀取這個(gè)副本數(shù)據(jù)寫(xiě)到 RDB 文件。

在執(zhí)行 SAVE 或 BGSAVE 命令創(chuàng)建一個(gè)新的 RDB 文件時(shí),程序會(huì)對(duì)數(shù)據(jù)庫(kù)中的鍵進(jìn)行檢查,已過(guò)期的鍵不會(huì)被保存到新創(chuàng)建的RDB 文件中。這既保證了快照的完整性,也允許主線(xiàn)程同時(shí)對(duì)數(shù)據(jù)進(jìn)行修改,避免了對(duì)正常業(yè)務(wù)的影響。

圖片


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

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

  • RDB 文件是一個(gè)很簡(jiǎn)潔的單文件,采用 二進(jìn)制 + 數(shù)據(jù)壓縮 的方式寫(xiě)磁盤(pán),文件體積小,數(shù)據(jù)恢復(fù)速度快。
  • RDB 的性能很好,需要進(jìn)行持久化時(shí),主進(jìn)程會(huì) fork 一個(gè)子進(jìn)程出來(lái),然后把持久化的工作交給子進(jìn)程,自己不會(huì)有相關(guān)的I/O操作。

缺點(diǎn)

  • RDB 容易造成數(shù)據(jù)的丟失。假設(shè)每5分鐘保存一次快照,如果 Redis 因?yàn)槟承┰虿荒苷9ぷ?,那么從上次產(chǎn)生快照到 Redis 出現(xiàn)問(wèn)題這段時(shí)間的數(shù)據(jù)就會(huì)丟失了。
  • RDB 使用 fork() 產(chǎn)生子進(jìn)程進(jìn)行數(shù)據(jù)的持久化,會(huì)阻塞主線(xiàn)程,如果數(shù)據(jù)比較大的話(huà)可能就會(huì)花費(fèi)點(diǎn)時(shí)間,造成 Redis 停止服務(wù)幾毫秒。如果數(shù)據(jù)量很大且CPU性能不是很好的時(shí)候,停止服務(wù)的時(shí)間甚至?xí)?秒。

另外,過(guò)于頻繁的執(zhí)行全量數(shù)據(jù)快照,有兩個(gè)嚴(yán)重的性能開(kāi)銷(xiāo):

  • 頻繁生成 RDB 文件寫(xiě)入磁盤(pán),磁盤(pán)壓力過(guò)大??赡軙?huì)出現(xiàn)上一個(gè) RDB 還未完成,下一個(gè)又開(kāi)始生成,陷入死循環(huán)。
  • fork 出 BGSAVE 子進(jìn)程這個(gè)動(dòng)作本身會(huì)阻塞主線(xiàn)程,主線(xiàn)程的內(nèi)存越大,阻塞時(shí)間越長(zhǎng)。

AOF寫(xiě)后日志,避免宕機(jī)數(shù)據(jù)丟失

1.什么是AOF寫(xiě)后日志?

AOF(Append Only File)寫(xiě)后日志,AOF 持久化就是將修改數(shù)據(jù)庫(kù)狀態(tài)的命令保存到 AOF 文件中,被寫(xiě)入的命令都是以 Redis 的命令請(qǐng)求協(xié)議格式保存的,Redis 的命令請(qǐng)求協(xié)議是純文本格式。

假設(shè) AOF 日志記錄了 Redis 實(shí)例創(chuàng)建以來(lái)所有的修改指令序列,那么就可以通過(guò)一個(gè)空的 Redis 實(shí)例順序執(zhí)行所有的指令,也就是“重放”,來(lái)恢復(fù)Redis當(dāng)前實(shí)例的內(nèi)存數(shù)據(jù)結(jié)構(gòu)的狀態(tài)。

寫(xiě)后日志和寫(xiě)前日志的對(duì)比

寫(xiě)前日志(WAL,Write Ahead Log):在實(shí)際寫(xiě)數(shù)據(jù)之前,將修改的數(shù)據(jù)寫(xiě)到日志文件中,故障恢復(fù)得以保證。比如 MySQL Innodb 存儲(chǔ)引擎中的 redo log(重做日志)便是記錄修改的數(shù)據(jù)日志,在實(shí)際修改數(shù)據(jù)前先記錄修改日志再執(zhí)行修改數(shù)據(jù)。

寫(xiě)后日志:先執(zhí)行“寫(xiě)”指令請(qǐng)求,將數(shù)據(jù)寫(xiě)入內(nèi)存,再記錄日志。

圖片


日志格式

當(dāng) Redis 接收到 “set key value” 命令將數(shù)據(jù)寫(xiě)入到內(nèi)存之后,會(huì)按照如下格式寫(xiě)入 AOF 文件:

  • *3:表示當(dāng)前指令分為三個(gè)部分,每部分都是 “$ + 數(shù)字” 開(kāi)頭,緊跟后面是該部分具體的命令、鍵、值
  • 數(shù)字:表示這部分的命令、鍵、值占用的字節(jié)大小。比如 “$3” 表示這部分包含三個(gè)字節(jié),也就是 set 指令。

圖片


寫(xiě)后日志的好處

寫(xiě)后日志避免了額外的檢查開(kāi)銷(xiāo),不需要對(duì)執(zhí)行的命令進(jìn)行語(yǔ)法檢查。如果使用寫(xiě)前日志的話(huà),就需要先檢查語(yǔ)法是否有誤,否則日志記錄了錯(cuò)誤的命令,在使用日志恢復(fù)的時(shí)候就會(huì)報(bào)錯(cuò)。另外,寫(xiě)后記錄日志,避免了阻塞當(dāng)前“寫(xiě)”指令的執(zhí)行。

2.寫(xiě)回策略

使用 AOF 也不是萬(wàn)無(wú)一失的,假如 Redis 剛執(zhí)行完指令,還沒(méi)記錄日志就宕機(jī)了,就有可能丟失這個(gè)命令的相關(guān)數(shù)據(jù);還有, AOF 避免了當(dāng)前命令的阻塞,但是可能會(huì)給下一個(gè)命令帶來(lái)阻塞的風(fēng)險(xiǎn)。AOF 日志是主線(xiàn)程執(zhí)行的,將日志寫(xiě)入磁盤(pán)過(guò)程中,如果磁盤(pán)壓力過(guò)大就會(huì)導(dǎo)致磁盤(pán)寫(xiě)操作很慢,導(dǎo)致后續(xù)的“寫(xiě)”指令阻塞。

發(fā)現(xiàn)了沒(méi),這兩個(gè)問(wèn)題與磁盤(pán)寫(xiě)回有關(guān),如果能合理控制“寫(xiě)”指令執(zhí)行完后 AOF 日志寫(xiě)回磁盤(pán)的時(shí)機(jī),問(wèn)題就可以迎刃而解。

為了提高文件的寫(xiě)入效率,當(dāng)用戶(hù)調(diào)用 write 函數(shù),將一些數(shù)據(jù)寫(xiě)入到文件時(shí)候,操作系統(tǒng)通常會(huì)將寫(xiě)入數(shù)據(jù)暫時(shí)保存在一個(gè)內(nèi)存緩沖區(qū)里,等到緩沖區(qū)的空間被填滿(mǎn)或者超過(guò)了制定的限制之后,才真正將緩沖區(qū)中的數(shù)據(jù)寫(xiě)入到磁盤(pán)里面。

這種做法雖然提高了效率,但也為寫(xiě)入數(shù)據(jù)帶來(lái)了安全問(wèn)題,因?yàn)槿绻?jì)算機(jī)發(fā)生停機(jī),那么保存在內(nèi)存緩沖區(qū)里的寫(xiě)入數(shù)據(jù)將會(huì)丟失。為此系統(tǒng)提供了 fsync 和 fdatasync 兩個(gè)同步函數(shù),它們可以強(qiáng)制讓操作系統(tǒng)立即將緩沖區(qū)中的數(shù)據(jù)寫(xiě)入到硬盤(pán)里,從而確保寫(xiě)入數(shù)據(jù)的安全性。

與之相對(duì)應(yīng) Redis 提供了 AOF 配置項(xiàng) appendfsync 寫(xiě)回策略來(lái)控制 AOF 持久化功能的效率和安全性。

appendfsync always     # 同步寫(xiě)回,寫(xiě)指令執(zhí)行完畢立即將 aof_buf 緩沖區(qū)中的內(nèi)容寫(xiě)到 AOF 文件。
appendfsync everysec   # 每秒寫(xiě)回,寫(xiě)指令執(zhí)行完畢,把日志寫(xiě)到 aof_buf 緩沖區(qū),每隔一秒同步到磁盤(pán),該策略為AOF的默認(rèn)策略。
appendfsync no         # 操作系統(tǒng)控制,寫(xiě)指令執(zhí)行完畢,把日志寫(xiě)到 aof_buf 緩沖區(qū),由操作系統(tǒng)決定何時(shí)寫(xiě)回磁盤(pán)。

3.AOF重寫(xiě)機(jī)制

由于 AOF 記錄的是一個(gè)個(gè)指令的內(nèi)容,這就會(huì)導(dǎo)致保存的文件太大,另外,故障恢復(fù)的時(shí)候需要執(zhí)行每一個(gè)指令,如果日志文件太大,整個(gè)恢復(fù)過(guò)程就會(huì)非常慢。為此,Reids 設(shè)計(jì)了 AOF 重寫(xiě)機(jī)制,提供了 bgrewriteaof 命令用于對(duì) AOF 文件進(jìn)行瘦身。

其原理就是開(kāi)辟一個(gè)子進(jìn)程對(duì)內(nèi)存進(jìn)行遍歷轉(zhuǎn)換成一系列 Redis 的操作指令,序列化到一個(gè)新的 AOF 日志文件中,序列化完畢后再將操作期間發(fā)生的增量 AOF 日志追加到這個(gè)新的 AOF 日志文件中,追加完畢后立即替換舊的 AOF 日志文件。瘦身工作就完成了。

重寫(xiě)機(jī)制有“多變一”的功能,將舊日志中的多條指令,在重寫(xiě)后就變成了一條指令。如下所示:三條 lpush 命令,經(jīng)過(guò) AOF 重寫(xiě)后生成一條,對(duì)于多次修改的場(chǎng)景,縮減效果明顯。

圖片

重寫(xiě)過(guò)程

和 AOF 日志由主線(xiàn)程寫(xiě)回不同,重寫(xiě)過(guò)程實(shí)際是由后臺(tái)子進(jìn)程 bgrewriteof 完成的,這也是為了避免阻塞主線(xiàn)程,導(dǎo)致性能下降。

總的來(lái)說(shuō),一共出現(xiàn)兩個(gè)日志,一次內(nèi)存數(shù)據(jù)拷貝,分別是舊的 AOF 日志和新的 AOF 重寫(xiě)日志和Redis 數(shù)據(jù)拷貝。大致流程如下圖所示:

圖片


在上圖中,Redis 會(huì)將重寫(xiě)過(guò)程中接收到的“寫(xiě)”指令操作同時(shí)記錄到舊的 AOF 緩沖區(qū)和新的 AOF 重寫(xiě)緩沖區(qū),這樣重寫(xiě)日志也保存了最新的操作,等到拷貝數(shù)據(jù)的所有操作記錄重寫(xiě)完成后,重寫(xiě)緩沖區(qū)記錄的最新操作也會(huì)寫(xiě)到新的 AOF 文件中。

每次 AOF 重寫(xiě)時(shí),Redis 會(huì)先執(zhí)行一次內(nèi)存拷貝,用于遍歷數(shù)據(jù)生成重寫(xiě)記錄。防止 AOF 重寫(xiě)過(guò)程失敗,導(dǎo)致原 AOF 文件被污染,無(wú)法做恢復(fù)使用。

使用兩個(gè)日志可以保證在重寫(xiě)過(guò)程中,新寫(xiě)入的數(shù)據(jù)不會(huì)丟失,并且保持?jǐn)?shù)據(jù)的一致性。

4.AOF 的優(yōu)點(diǎn)和缺點(diǎn)

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

  • AOF比RDB可靠。可以靈活制定不同的fsync策略。
  • AOF日志文件是一個(gè)純追加的文件。就算是遇到突然停電的情況,也不會(huì)出現(xiàn)日志的定位或者損壞問(wèn)題。
  • 當(dāng)AOF文件過(guò)大時(shí),Redis會(huì)自動(dòng)在后臺(tái)進(jìn)行重寫(xiě)。
  • AOF以命令格式存儲(chǔ)于文件中,在數(shù)據(jù)恢復(fù)時(shí),AOF文件比RDB文件更容易讓開(kāi)發(fā)人員看懂,并加以修改。

缺點(diǎn)

  • 在相同的數(shù)據(jù)集下,AOF文件的大小一般會(huì)比RDB文件大。
  • 在某些fsync策略下,AOF的速度會(huì)比RDB慢。通常fsync設(shè)置為每秒一次就能獲得比較高的性能,而在禁止fsync的情況下速度可以達(dá)到RDB的水平。

混合日志模型

重啟 Redis 時(shí),我們很少使用 RDB 來(lái)恢復(fù)內(nèi)存狀態(tài),因?yàn)榭赡軄G失大量數(shù)據(jù)。通常采用 AOF 日志重放,但是重放 AOF 日志性能相對(duì) RDB 來(lái)說(shuō)要慢很多,在Redis實(shí)例很大的情況下,啟動(dòng)需要花費(fèi)很長(zhǎng)時(shí)間。

Redis 4.0 為了解決這個(gè)問(wèn)題,提供了一個(gè)新的持久化選項(xiàng)--混合持久化,將 RDB 文件的內(nèi)容和增量 AOF 日志文件存放到一起,這里的 AOF 日志不再是全量的日志,而是自持久化開(kāi)始到持久化結(jié)束的這段時(shí)間發(fā)生的增量 AOF 日志,通常這部分日志很小。

圖片


在 Redis 重啟的時(shí)候,先加載 RDB 的內(nèi)容,然后再重放增量 AOF 日志,這樣的操作既保證了 Redis 重啟速度,又降低數(shù)據(jù)丟失風(fēng)險(xiǎn)。

總結(jié)

  • Redis 提供 RDB 快照持久化方案,記錄某一時(shí)刻數(shù)據(jù)狀態(tài)
  • Redis 通過(guò)寫(xiě)時(shí)復(fù)制技術(shù)設(shè)計(jì)了BGSAVE,避免執(zhí)行快照期間對(duì)讀寫(xiě)指令的影響。
  • Redis 提供了 AOF 寫(xiě)后日志持久化方案,記錄每一條操作指令。
  • Redis 通過(guò) AOF 重寫(xiě)方案,避免 AOF文件過(guò)大。
  • Redis 提供了混合持久化的方案,RDB + AOF 實(shí)現(xiàn)持久化保證數(shù)據(jù)可靠性,同時(shí)支持故障后的數(shù)據(jù)快速恢復(fù)。

參考

Redis設(shè)計(jì)與實(shí)(https://weread.qq.com/web/reader/d35323e0597db0d35bd957bk73532580243735b90b45ac8)

Redis核心技術(shù)與實(shí)戰(zhàn)(https://time.geekbang.org/column/intro/329)

圖片

責(zé)任編輯:武曉燕 來(lái)源: 政采云技術(shù)
相關(guān)推薦

2021-07-18 07:59:42

RedisRDBAOF

2019-05-17 08:55:49

RedisRDBAOF

2021-03-10 00:02:01

Redis

2024-03-26 00:03:08

Redis數(shù)據(jù)RDB

2020-01-06 14:54:31

RDBAOFRedis

2024-09-12 08:49:53

2020-12-11 11:40:37

RDBAOFRedis

2024-09-06 17:49:46

2021-10-18 07:43:30

RedisAOF日志RDB快照

2023-03-13 08:08:48

數(shù)據(jù)庫(kù)Redis

2021-02-04 08:01:35

RedisRDBAOF

2025-01-22 10:16:46

RedisRDBAOF

2024-09-29 09:25:53

2024-12-20 12:15:06

RedisRDB持久化

2021-12-12 10:29:41

AOFRedisAOF日志

2023-09-12 10:49:44

Redis數(shù)據(jù)庫(kù)

2021-05-28 10:25:39

Redis數(shù)據(jù)庫(kù)內(nèi)存

2025-03-14 08:00:00

AOFRedis數(shù)據(jù)庫(kù)

2024-11-22 08:31:32

Redis數(shù)據(jù)持久化高可用

2019-11-18 16:20:48

RedisRDB數(shù)據(jù)庫(kù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)