0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Redis在服務(wù)器宕機(jī)時(shí)如何避免數(shù)據(jù)丟失呢?

jf_ro2CN3Fa ? 來源:稀土掘金 ? 2023-02-12 16:21 ? 次閱讀

前言

如果有人問你:"你會(huì)把 Redis 用在什么業(yè)務(wù)場(chǎng)景下?"

我想你大概率會(huì)說:"我會(huì)把它當(dāng)作緩存使用,因?yàn)樗押蠖藬?shù)據(jù)庫中的數(shù)據(jù)存儲(chǔ)在內(nèi)存中,然后直接從內(nèi)存中讀取數(shù)據(jù),響應(yīng)速度會(huì)非???。"

沒錯(cuò),這確實(shí)是 Redis 的一個(gè)普遍使用場(chǎng)景,但是,這里也有一個(gè)絕對(duì)不能忽略的問題:「一旦服務(wù)器宕機(jī),內(nèi)存中的數(shù)據(jù)將全部丟失」

目前,Redis 的持久化主要有兩大機(jī)制,即 「AOF(Append Only File)日志和 RDB(Redis DataBase) 快照」 。

AOF

日志是如何實(shí)現(xiàn)的

說到日志,我們比較熟悉的是數(shù)據(jù)庫的寫前日志(Write Ahead Log, WAL),在實(shí)際寫數(shù)據(jù)前,先把修改的數(shù)據(jù)記到日志文件中,以便故障時(shí)進(jìn)行恢復(fù)。不過,AOF 日志正好相反,它是寫后日志,"寫后"的意思是 Redis 是先執(zhí)行命令,把數(shù)據(jù)寫入內(nèi)存,然后才記錄日志。

a8d44292-aaa5-11ed-bfe3-dac502259ad0.jpg

AOF日志是如何實(shí)現(xiàn)的

AOF 里記錄的是 Redis 收到的每一條命令,這些命令是以文本形式保存的。

我們以 Redis 收到“set testkey testvalue”命令后記錄的日志為例,看看 AOF 日志的內(nèi)容。其中,“*3”表示當(dāng)前命令有三個(gè)部分,每部分都是由“數(shù)字開頭,后面緊跟著具體的命令、鍵或值。這里,數(shù)字表示這部分中的命令、鍵或值一共有多少字節(jié)。例如,3 set”表示這部分有 3 個(gè)字節(jié),也就是“set”命令。

a8e737da-aaa5-11ed-bfe3-dac502259ad0.jpg

AOF日志是如何實(shí)現(xiàn)的

寫后日志的優(yōu)勢(shì)與風(fēng)險(xiǎn)

「為了避免額外的檢查開銷,Redis 在向 AOF 里面記錄日志的時(shí)候,并不會(huì)先去對(duì)這些命令進(jìn)行語法檢查」

如果先記日志再執(zhí)行命令的話,日志中就有可能記錄了錯(cuò)誤的命令,Redis 在使用日志恢復(fù)數(shù)據(jù)時(shí),就可能會(huì)出錯(cuò)。而寫后日志這種方式,就是先讓系統(tǒng)執(zhí)行命令,只有命令能執(zhí)行成功,才會(huì)被記錄到日志中,否則,系統(tǒng)就會(huì)直接向客戶端報(bào)錯(cuò)。

所以,Redis 使用寫后日志這一方式的一大好處是,可以避免出現(xiàn)記錄錯(cuò)誤命令的情況。

除此之外,寫后日志一個(gè)好處:它是在命令執(zhí)行后才記錄日志,「不會(huì)阻塞當(dāng)前的寫操作」

AOF 也有兩個(gè)潛在的風(fēng)險(xiǎn):

風(fēng)險(xiǎn)一:如果剛執(zhí)行完一個(gè)命令,還沒有來得及記日志就宕機(jī)了,那么這個(gè)命令和相應(yīng)的數(shù)據(jù)就有丟失的風(fēng)險(xiǎn)。

如果此時(shí) Redis 是用作緩存,還可以從后端數(shù)據(jù)庫重新讀入數(shù)據(jù)進(jìn)行恢復(fù)。

如果 Redis 是直接用作數(shù)據(jù)庫的話,此時(shí),因?yàn)槊顩]有記入日志,所以就無法用日志進(jìn)行恢復(fù)了。

風(fēng)險(xiǎn)二:AOF 雖然避免了對(duì)當(dāng)前命令的阻塞,但可能會(huì)給下一個(gè)操作帶來阻塞風(fēng)險(xiǎn)。

AOF 日志也是在主線程中執(zhí)行(寫回策略為 always 時(shí)),如果在把日志文件寫入磁盤時(shí),磁盤寫壓力大,就會(huì)導(dǎo)致寫盤很慢,進(jìn)而導(dǎo)致后續(xù)的操作也無法執(zhí)行了。

這兩個(gè)風(fēng)險(xiǎn)都是和 AOF 寫回磁盤的時(shí)機(jī)相關(guān)的。這也就意味著,如果我們能夠控制一個(gè)寫命令執(zhí)行完后 AOF 日志寫回磁盤的時(shí)機(jī),這兩個(gè)風(fēng)險(xiǎn)就解除了。

日志的寫回策略

AOF 機(jī)制一共有三種寫回策略,也就是 AOF 配置項(xiàng) appendfsync 的三個(gè)可選值。

「Always 同步寫回」 :每個(gè)寫命令執(zhí)行完,立馬同步地將日志寫回磁盤;

「Everysec 每秒寫回」 :每個(gè)寫命令執(zhí)行完,只是先把日志寫到 AOF 文件的內(nèi)存緩沖區(qū),每隔一秒把緩沖區(qū)中的內(nèi)容寫入磁盤;

「No 操作系統(tǒng)控制的寫回」 :每個(gè)寫命令執(zhí)行完,只是先把日志寫到 AOF 文件的內(nèi)存緩沖區(qū),由操作系統(tǒng)決定何時(shí)將緩沖區(qū)內(nèi)容寫回磁盤。

針對(duì)避免主線程阻塞和減少數(shù)據(jù)丟失問題,這三種寫回策略都無法做到兩全其美。

a8fcf192-aaa5-11ed-bfe3-dac502259ad0.jpg

日志的寫回策略

我們就可以根據(jù)系統(tǒng)對(duì)高性能和高可靠性的要求,來選擇使用哪種寫回策略了。

想要獲得高性能,就選擇 No 策略;

想要得到高可靠性保證,就選擇 Always 策略;

允許數(shù)據(jù)有一點(diǎn)丟失,又希望性能別受太大影響的話,那么就選擇 Everysec 策略。

日志的重寫

重寫的作用

AOF 是以文件的形式在記錄接收到的所有寫命令。「隨著接收的寫命令越來越多,AOF 文件會(huì)越來越大」 。這也就意味著,我們一定要小心 AOF 文件過大帶來的性能問題,主要在于以下三個(gè)方面:

一是,文件系統(tǒng)本身對(duì)文件大小有限制,無法保存過大的文件;

二是,如果文件太大,之后再往里面追加命令記錄的話,效率也會(huì)變低;

三是,如果發(fā)生宕機(jī),AOF 中記錄的命令要一個(gè)個(gè)被重新執(zhí)行,用于故障恢復(fù),如果日志文件太大,整個(gè)恢復(fù)過程就會(huì)非常緩慢,這就會(huì)影響到 Redis 的正常使用。

AOF 重寫機(jī)制就是在重寫時(shí),Redis 根據(jù)數(shù)據(jù)庫的現(xiàn)狀創(chuàng)建一個(gè)新的 AOF 文件,也就是說,「讀取數(shù)據(jù)庫中的所有鍵值對(duì),然后對(duì)每一個(gè)鍵值對(duì)用一條命令記錄它的寫入」 。重寫機(jī)制具有“多變一”功能。所謂的“多變一”,也就是說,舊日志文件中的多條命令,在重寫后的新日志中變成了一條命令。

a90b915c-aaa5-11ed-bfe3-dac502259ad0.jpg

重寫的作用

重寫的過程

AOF 日志由主線程寫回不同,重寫過程是由「后臺(tái)子進(jìn)程 bgrewriteaof 來完成的,這也是為了避免阻塞主線程」 ,導(dǎo)致數(shù)據(jù)庫性能下降。

我把重寫的過程總結(jié)為“「一個(gè)拷貝,兩處日志」 ”。

“一個(gè)拷貝”就是指,每次執(zhí)行重寫時(shí),主線程 fork 出后臺(tái)的 bgrewriteaof 子進(jìn)程。此時(shí),fork 會(huì)把主線程的內(nèi)存拷貝一份給 bgrewriteaof 子進(jìn)程,這里面就包含了數(shù)據(jù)庫的最新數(shù)據(jù)。然后,bgrewriteaof 子進(jìn)程就可以在不影響主線程的情況下,逐一把拷貝的數(shù)據(jù)寫成操作,記入重寫日志。

第一處日志,指的是因?yàn)橹骶€程未阻塞,仍然可以處理新來的操作,Redis 會(huì)把這個(gè)操作寫到它的緩沖區(qū)。這樣一來,即使宕機(jī)了,這個(gè) AOF 日志的操作仍然是齊全的,可以用于恢復(fù)。

第二處日志,就是指新的 AOF 重寫日志。這個(gè)操作也會(huì)被寫到重寫日志的緩沖區(qū)。這樣,重寫日志也不會(huì)丟失最新的操作。等到拷貝數(shù)據(jù)的所有操作記錄重寫完成后,重寫日志記錄的這些最新操作也會(huì)寫入新的 AOF 文件,以保證數(shù)據(jù)庫最新狀態(tài)的記錄。

此時(shí),我們就可以用新的 AOF 文件替代舊文件了。

a91f24d8-aaa5-11ed-bfe3-dac502259ad0.jpg

重寫的過程

總結(jié)來說,每次 AOF 重寫時(shí),Redis 會(huì)先執(zhí)行一個(gè)內(nèi)存拷貝,用于重寫;然后,使用兩個(gè)日志保證在重寫過程中,新寫入的數(shù)據(jù)不會(huì)丟失。而且,「因?yàn)?Redis 采用子進(jìn)程進(jìn)行日志重寫,所以,這個(gè)過程并不會(huì)阻塞主線程」

正因?yàn)橛涗浀氖遣僮髅?,而不是?shí)際的數(shù)據(jù),所以,用 AOF 方法進(jìn)行故障恢復(fù)的時(shí)候,需要逐一把操作日志都執(zhí)行一遍。如果操作日志非常多,Redis 就會(huì)恢復(fù)得很緩慢,影響到正常使用。這當(dāng)然不是理想的結(jié)果。那么,還有沒有既可以保證可靠性,還能在宕機(jī)時(shí)實(shí)現(xiàn)快速恢復(fù)的其他方法呢?

RDB

對(duì) Redis 來說,它實(shí)現(xiàn)類似照片記錄效果的方式,把某一時(shí)刻的狀態(tài)以文件的形式寫到磁盤上,也就是快照(RDB 文件)。這樣一來,即使宕機(jī),快照文件也不會(huì)丟失,數(shù)據(jù)的可靠性也就得到了保證。

和 AOF 相比,RDB 記錄的是某一時(shí)刻的數(shù)據(jù),并不是操作,所以,在做數(shù)據(jù)恢復(fù)時(shí),我們可以直接把 RDB 文件讀入內(nèi)存,很快地完成恢復(fù)。

快照的原理

Redis 提供了兩個(gè)命令來生成 RDB 文件,分別是 save 和 bgsave。

「save」 :在主線程中執(zhí)行,會(huì)導(dǎo)致阻塞;

「bgsave」 :創(chuàng)建一個(gè)子進(jìn)程,專門用于寫入 RDB 文件,避免了主線程的阻塞,這也是 Redis RDB 文件生成的默認(rèn)配置。

我們可以通過 bgsave 命令來執(zhí)行全量快照,這既提供了數(shù)據(jù)的可靠性保證,也避免了對(duì) Redis 的性能影響。

在執(zhí)行快照的同時(shí),Redis 就會(huì)借助操作系統(tǒng)提供的寫時(shí)復(fù)制技術(shù)(Copy-On-Write, COW),正常處理寫操作。bgsave 子進(jìn)程是由主線程 fork 生成的,可以共享主線程的所有內(nèi)存數(shù)據(jù)。bgsave 子進(jìn)程運(yùn)行后,開始讀取主線程的內(nèi)存數(shù)據(jù),并把它們寫入 RDB 文件。

如果主線程對(duì)這些數(shù)據(jù)也都是讀操作(例如圖中的鍵值對(duì) A),那么,主線程和 bgsave 子進(jìn)程相互不影響。但是,如果主線程要修改一塊數(shù)據(jù)(例如圖中的鍵值對(duì) C),那么,這塊數(shù)據(jù)就會(huì)被復(fù)制一份,生成該數(shù)據(jù)的副本(鍵值對(duì) C’)。然后,主線程在這個(gè)數(shù)據(jù)副本上進(jìn)行修改。同時(shí),bgsave 子進(jìn)程可以繼續(xù)把原來的數(shù)據(jù)(鍵值對(duì) C)寫入 RDB 文件。

a934a358-aaa5-11ed-bfe3-dac502259ad0.jpg

快照的原理

這樣既保證了快照的完整性,也允許主線程同時(shí)對(duì)數(shù)據(jù)進(jìn)行修改,避免了對(duì)正常業(yè)務(wù)的影響。

混合 AOF/RDB

雖然 bgsave 執(zhí)行時(shí)不阻塞主線程,但是,如果頻繁地執(zhí)行全量快照,也會(huì)帶來兩方面的開銷。

一方面,頻繁將全量數(shù)據(jù)寫入磁盤,會(huì)給磁盤帶來很大壓力,多個(gè)快照競(jìng)爭(zhēng)有限的磁盤帶寬,前一個(gè)快照還沒有做完,后一個(gè)又開始做了,容易造成惡性循環(huán)(所以,在 Redis 中如果有一個(gè) bgsave 在運(yùn)行,就不會(huì)再啟動(dòng)第二個(gè) bgsave 子進(jìn)程)。

另一方面,bgsave 子進(jìn)程需要通過 fork 操作從主線程創(chuàng)建出來。雖然,子進(jìn)程在創(chuàng)建后不會(huì)再阻塞主線程,但是,「fork 這個(gè)創(chuàng)建過程本身會(huì)阻塞主線程」 ,而且主線程的內(nèi)存越大,阻塞時(shí)間越長(zhǎng)。

Redis 4.0 中提出了一個(gè)混合使用 AOF 日志和內(nèi)存快照的方法。簡(jiǎn)單來說,「內(nèi)存快照以一定的頻率執(zhí)行,在兩次快照之間,使用 AOF 日志記錄這期間的所有命令操作」 。這樣一來,快照不用很頻繁地執(zhí)行,這就避免了頻繁 fork 對(duì)主線程的影響。而且,AOF 日志也只用記錄兩次快照間的操作,也就是說,不需要記錄所有操作了,因此,就不會(huì)出現(xiàn)文件過大的情況了,也可以避免重寫開銷。

a9475aa2-aaa5-11ed-bfe3-dac502259ad0.jpg

混合 AOF/RDB

總結(jié)

最后,關(guān)于 AOF 和 RDB 的選擇問題,我想再給你提三點(diǎn)建議:

數(shù)據(jù)不能丟失時(shí),內(nèi)存快照和 AOF 的混合使用是一個(gè)很好的選擇;

如果允許分鐘級(jí)別的數(shù)據(jù)丟失,可以只使用 RDB;

如果只用 AOF,優(yōu)先使用 everysec 的配置選項(xiàng),因?yàn)樗诳煽啃院托阅苤g取了一個(gè)平衡。








審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Redis
    +關(guān)注

    關(guān)注

    0

    文章

    370

    瀏覽量

    10830
  • Fork
    +關(guān)注

    關(guān)注

    0

    文章

    14

    瀏覽量

    3280

原文標(biāo)題:宕機(jī)了,Redis 如何避免數(shù)據(jù)丟失?

文章出處:【微信號(hào):芋道源碼,微信公眾號(hào):芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    如何在redis windows上連接阿里云服務(wù)器上的redis

    rediswindows上連接阿里云服務(wù)器上的redis連接失敗連接后不能使用報(bào)錯(cuò)等
    發(fā)表于 07-25 07:47

    Docker部署Redis服務(wù)器集群的方法

    Docker部署Redis服務(wù)器集群
    發(fā)表于 06-13 09:12

    介紹redis服務(wù)器運(yùn)行過程

    Redis服務(wù)器負(fù)責(zé)與多個(gè)客戶端建立網(wǎng)絡(luò)連接,處理客戶端發(fā)送三個(gè)的命令請(qǐng)求,在數(shù)據(jù)庫中爆粗你客戶單執(zhí)行命令所產(chǎn)生的數(shù)據(jù),并通過資源管理來維持服務(wù)器
    發(fā)表于 03-07 10:15 ?547次閱讀

    刀片服務(wù)器服務(wù)器數(shù)據(jù)丟失有哪兩種情況

    隨著科技的發(fā)展,現(xiàn)在越來越多的企業(yè)都選用了刀片服務(wù)器,但是即便刀片服務(wù)器的性能強(qiáng)大,但是也避免不了一些客觀的因素導(dǎo)致刀片服務(wù)器受損使得數(shù)據(jù)
    的頭像 發(fā)表于 04-14 14:30 ?2260次閱讀

    服務(wù)器出現(xiàn)宕機(jī)時(shí)的處理方式都有哪些

    瓶頸問題等都會(huì)出現(xiàn)服務(wù)器宕機(jī),這也對(duì)企業(yè)的正常開展業(yè)務(wù)造成了一定的阻礙,當(dāng)出現(xiàn)服務(wù)器宕機(jī)現(xiàn)象又應(yīng)該怎么處理? 首先,要明白
    發(fā)表于 11-12 14:19 ?3324次閱讀

    谷歌服務(wù)器再次全球宕機(jī)

    12月15日,美國(guó)當(dāng)?shù)貢r(shí)間周一,谷歌服務(wù)器再次全球宕機(jī)。不過,該公司已經(jīng)找到了導(dǎo)致數(shù)十項(xiàng)服務(wù)癱瘓的罪魁禍?zhǔn)?,即?nèi)部技術(shù)故障所致。
    的頭像 發(fā)表于 12-15 14:22 ?2060次閱讀

    針對(duì)Redis服務(wù)我們應(yīng)該避免哪些性能浪費(fèi)

    ],最新的用戶關(guān)系[2],都存儲(chǔ) Redis 中,大量的查詢擊中 Redis,而不走 MySQL。 那么,針對(duì) Redis 服務(wù),我們能做
    的頭像 發(fā)表于 10-28 14:07 ?1314次閱讀

    Redis持久化機(jī)制的實(shí)現(xiàn)原理和使用技巧

    Redis數(shù)據(jù)存儲(chǔ)在內(nèi)存中,宕機(jī)或重啟都會(huì)使內(nèi)存數(shù)據(jù)全部丟失, Redis的持久化機(jī)制用來保證
    的頭像 發(fā)表于 09-13 16:42 ?973次閱讀

    修復(fù) Windows VPS 服務(wù)器宕機(jī)的簡(jiǎn)單步驟

    需要了解一些方法,以便 在任何時(shí)候意外發(fā)生VPS宕機(jī)時(shí)嘗試自行恢復(fù)VPS 。 ? 首先,您可以通過任務(wù)管理檢查 RAM 和 CPU 使用情況。當(dāng)使用量超過您的 VPS 資源的最|佳水平時(shí),它會(huì)導(dǎo)致您的 VPS 承受沉重的服務(wù)器
    的頭像 發(fā)表于 02-23 15:14 ?861次閱讀

    Redis服務(wù)器的內(nèi)存耗盡后,Redis會(huì)如何處理?

    作為一臺(tái)服務(wù)器來說,內(nèi)存并不是無限的,所以總會(huì)存在內(nèi)存耗盡的情況,那么當(dāng) Redis 服務(wù)器的內(nèi)存耗盡后,如果繼續(xù)執(zhí)行請(qǐng)求命令,Redis 會(huì)如何處理
    的頭像 發(fā)表于 03-08 09:26 ?540次閱讀

    服務(wù)器宕機(jī)出現(xiàn)的原因與解決辦法

    和排名,因而在租用服務(wù)器時(shí),建議站長(zhǎng)選擇想美國(guó)服務(wù)器這種出現(xiàn)宕機(jī)概率比較低的服務(wù)器。服務(wù)器使用
    的頭像 發(fā)表于 03-24 10:54 ?2385次閱讀

    服務(wù)器數(shù)據(jù)恢復(fù)—非正常關(guān)機(jī)導(dǎo)致服務(wù)器文件丟失數(shù)據(jù)恢復(fù)案例

    ;分析: 服務(wù)器在運(yùn)行過程中自動(dòng)關(guān)機(jī)且無法啟動(dòng),服務(wù)器管理員對(duì)服務(wù)器進(jìn)行修復(fù)后成功啟動(dòng)服務(wù)器,但服務(wù)器上原來的某個(gè)分區(qū)無法掛載。管理員將無
    的頭像 發(fā)表于 01-19 13:42 ?435次閱讀

    服務(wù)器數(shù)據(jù)恢復(fù)】斷電導(dǎo)致服務(wù)器RAID信息丟失數(shù)據(jù)恢復(fù)案例

    故障之前出現(xiàn)過幾次意外斷電的情況,服務(wù)器斷電重啟后沒有發(fā)現(xiàn)異常,直到最后一次斷電重啟后RAID報(bào)錯(cuò):“無法找到存儲(chǔ)設(shè)備”,進(jìn)入RAID管理模塊后進(jìn)行任何操作都會(huì)死機(jī),服務(wù)器管理員多次重啟服務(wù)器仍然無法進(jìn)入系統(tǒng)。為了防止
    的頭像 發(fā)表于 02-18 13:53 ?586次閱讀

    假如服務(wù)器數(shù)據(jù)丟失,如何快速恢復(fù)丟失數(shù)據(jù)?

    服務(wù)器數(shù)據(jù)丟失后,快速恢復(fù)丟失數(shù)據(jù)是至關(guān)重要的,以避免
    的頭像 發(fā)表于 08-08 16:59 ?315次閱讀

    服務(wù)器數(shù)據(jù)恢復(fù)—硬盤出現(xiàn)壞扇區(qū)導(dǎo)致網(wǎng)站服務(wù)器宕機(jī)數(shù)據(jù)恢復(fù)案例

    服務(wù)器數(shù)據(jù)恢復(fù)環(huán)境: 一臺(tái)linux操作系統(tǒng)服務(wù)器上跑了幾十個(gè)網(wǎng)站,服務(wù)器上只有一塊SATA硬盤。 服務(wù)器故障:
    的頭像 發(fā)表于 09-12 12:02 ?158次閱讀