溫馨提示×

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

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

Redis數(shù)據(jù)丟失如何解決

發(fā)布時(shí)間:2021-07-26 16:02:17 來(lái)源:億速云 閱讀:244 作者:Leah 欄目:數(shù)據(jù)庫(kù)

這篇文章將為大家詳細(xì)講解有關(guān)Redis數(shù)據(jù)丟失如何解決,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。

什么是 AOF 日志?

AOF(Append Only File)日志稱之為「寫后日志」,即是命令先執(zhí)行完成,把數(shù)據(jù)寫入內(nèi)存,然后才會(huì)記錄日志。

AOF日志(文本形式)會(huì)將收到每一條的命令且執(zhí)行成功的命令以一定的格式寫入到文本中(追加的方式)。

「寫后日志有什么好處呢?」 如下:

  1. 鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術(shù)社區(qū)

  2.  對(duì)于寫前日志無(wú)論命令是否執(zhí)行成功都會(huì)被記錄,但是Redis的寫后日志則只有命令執(zhí)行成功才會(huì)被寫入日志,避免了日志中存在錯(cuò)誤命令;

  3.  同時(shí)由于是命令執(zhí)行成功之后才會(huì)寫入日志,因此不會(huì)阻塞當(dāng)前命令的執(zhí)行。

但是AOF日志也有「潛在的風(fēng)險(xiǎn)」,分析如下:

   1.  由于是寫后日志,如果在命令執(zhí)行成功之后,在日志未寫入磁盤之前服務(wù)器突然宕機(jī),那重啟恢復(fù)數(shù)據(jù)的時(shí)候,這部分的數(shù)據(jù)肯定在日志文件中不存在了,那么將會(huì)丟失。(無(wú)法通過(guò)后臺(tái)數(shù)據(jù)庫(kù)恢復(fù)的情況下)

  2.  雖然不會(huì)阻塞當(dāng)前命令的執(zhí)行,由于記錄日志也是在主線程中(Redis是單線程),如果日志寫入磁盤的時(shí)候突然阻塞了,肯定會(huì)影響下一個(gè)命令的執(zhí)行。

為了解決上面的風(fēng)險(xiǎn),AOF日志提供了三種回寫策略。

三種寫回策略

AOF機(jī)制提供了三種回寫策略,這些都在appendfsync配置,如下:

  1. 鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術(shù)社區(qū)

  2.  Always(同步寫回):命令執(zhí)行完成,立馬同步的將日志寫入磁盤

  3.  Everysec(每秒寫回):命令執(zhí)行完成后,先將日志寫入 AOF 文件的內(nèi)存緩沖區(qū),每隔一秒把緩沖區(qū)中內(nèi)容寫入磁盤。

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

其實(shí)這三中寫回策略都無(wú)法解決主線程的阻塞和數(shù)據(jù)丟失的問(wèn)題,分析如下:

  1. 鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術(shù)社區(qū)

  2.  同步寫回:基本不丟失數(shù)據(jù),但是每步操作都會(huì)有一個(gè)慢速的落盤操作,不可避免的影響主線程性能。

  3.  每秒寫回:采用一秒寫一次到 AOF 日志文件中,但是一旦宕機(jī)還是會(huì)丟失一秒的數(shù)據(jù)。

  4.  操作系統(tǒng)控制的寫回:在寫完緩沖區(qū)之后則會(huì)寫入磁盤,但是數(shù)據(jù)始終在緩沖區(qū)的時(shí)間內(nèi)一旦宕機(jī),數(shù)據(jù)還是會(huì)丟失。

以上三種策略優(yōu)缺點(diǎn)總結(jié)如下表:

Redis數(shù)據(jù)丟失如何解決

日志文件太大怎么辦?

隨著數(shù)據(jù)量的增大,AOF日志文件難免會(huì)很大,這樣將會(huì)導(dǎo)致寫入和恢復(fù)數(shù)據(jù)都將變得非常慢。此時(shí)AOF提供了一種「重寫機(jī)制」解決這一問(wèn)題。

?重寫機(jī)制理解起來(lái)很簡(jiǎn)單,即是Redis會(huì)創(chuàng)建一個(gè)新的AOF日志文件,將每個(gè)鍵值對(duì)最終的值用一條命令寫入日志文件中。

比如讀取了鍵值對(duì)key1:value1,重寫機(jī)制會(huì)在新的AOF日志文件中記錄如下一條命令:

set key1 value1

其實(shí)即是記錄多次修改的最終的值記錄在新的AOF日志文件中,這樣當(dāng)恢復(fù)數(shù)據(jù)時(shí)可直接執(zhí)行該命令。

「為什么重寫機(jī)制能夠縮小文件呢?」 當(dāng)一個(gè)鍵值被多次修改后,AOF日志文件中將會(huì)記錄多次修改鍵值的命令,重寫機(jī)制是根據(jù)這個(gè)鍵值最新?tīng)顟B(tài)為它生成「寫入」命令,這樣舊文件中的「多條」命令在重寫后的新日志中變成了「一條」命令。

作者畫了一張重寫流程圖,僅供參考,如下:

Redis數(shù)據(jù)丟失如何解決

重寫機(jī)制流程

AOF重寫會(huì)阻塞主線程嗎?

AOF重寫雖然能夠縮減日志文件的大小,達(dá)到減少日志記錄和數(shù)據(jù)恢復(fù)的時(shí)間,但是在數(shù)據(jù)量非常的大情況下把整個(gè)數(shù)據(jù)庫(kù)重寫后的日志寫入磁盤是一個(gè)非常耗時(shí)的過(guò)程,難道不會(huì)阻塞主線程嗎?

「答案是:不會(huì)阻塞主線程」;因?yàn)锳OF重寫過(guò)程是由后臺(tái)子進(jìn)程bgrewriteaof來(lái)完成的,這也是為了避免阻塞主線程,導(dǎo)致數(shù)據(jù)庫(kù)性能下降。

其實(shí)重寫的過(guò)程分為兩個(gè)階段:「一個(gè)拷貝,兩處日志」。

「一個(gè)拷貝」:指每次執(zhí)行重寫時(shí),主線程都fork一個(gè)子線程bgrewriteaof,主線程會(huì)把內(nèi)存數(shù)據(jù)拷貝一份到子線程,此時(shí)子線程中包含了數(shù)據(jù)庫(kù)的最新數(shù)據(jù)。然后子線程就能在不影響主線程的情況下進(jìn)行AOF重寫了。

「兩處日志」是什么?如下:

  1. 鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術(shù)社區(qū)

  2.  第一處日志:子線程重寫并未阻塞主線程,此時(shí)主線程仍然會(huì)處理請(qǐng)求,此時(shí)的AOF日志仍然正在記錄著,這樣即使宕機(jī)了,數(shù)據(jù)也是齊全的。第一處日志即是值主線程正在使用的日志。

  3.  第二處日志:指新的AOF重寫日志;重寫過(guò)程中的操作也會(huì)被寫到重寫日志緩沖區(qū),這樣重寫日志也不會(huì)丟失最新的操作。等到拷貝數(shù)據(jù)的所有操作記錄重寫完成后,重寫日志記錄的這些最新操作也會(huì)寫入新的 AOF 文件,以保證數(shù)據(jù)庫(kù)最新?tīng)顟B(tài)的記錄。此時(shí),我們就可以用新的 AOF 文件替代舊文件了。

?「總結(jié)」:Redis在進(jìn)行AOF重寫時(shí),會(huì)fork一個(gè)子線程(不會(huì)阻塞主線程)并進(jìn)行內(nèi)存拷貝用于重寫,然后使用兩個(gè)日志保證重寫過(guò)程中,新寫入的數(shù)據(jù)不會(huì)丟失。

AOF的缺點(diǎn)

雖說(shuō)進(jìn)行了日志重寫后,AOF日志文件會(huì)縮減很多,但是在數(shù)據(jù)恢復(fù)過(guò)程中仍然是一條命令一條命令(由于單線程,只能順序執(zhí)行)的執(zhí)行恢復(fù)數(shù)據(jù),這個(gè)恢復(fù)的過(guò)程非常緩慢。

總結(jié)

AOF這種通過(guò)逐一記錄操作命令的日志方式,提供了三種寫回策略保證數(shù)據(jù)的可靠性,分別是Always、Everysec和No,這三種策略在可靠性上是從高到低,而在性能上則是從低到高。

為了避免日志文件過(guò)大,Redis提供了重寫的機(jī)制,每次重寫都fork一個(gè)子線程,拷貝內(nèi)存數(shù)據(jù)進(jìn)行重寫,將多條命令縮減成一條生成鍵值對(duì)的命令,最終重寫的日志作為新的日志。

什么是RDB?

RDB(Redis DataBase)是另外一種持久化方式:內(nèi)存快照。

?RDB記錄的是「某一個(gè)時(shí)刻」的內(nèi)存數(shù)據(jù),并不是操作命令。

這種方式類似于拍照,只保留某一時(shí)刻的形象。內(nèi)存快照是將某一時(shí)刻的狀態(tài)以文件的形式寫入磁盤。這樣即使宕機(jī)了,數(shù)據(jù)也不會(huì)丟失,這個(gè)快照文件就稱為RDB文件。

?由于記錄的是某個(gè)時(shí)刻的內(nèi)存數(shù)據(jù),數(shù)據(jù)恢復(fù)非??斓?,不需要像AOF日志逐一執(zhí)行記錄的命令。

給哪些數(shù)據(jù)做快照?

為了保證數(shù)據(jù)的可靠性,Redis執(zhí)行的「全量快照」,也就是把內(nèi)存中的所有數(shù)據(jù)都寫到磁盤中。

隨著數(shù)據(jù)量的增大,一次性把全部數(shù)據(jù)都寫到磁盤中勢(shì)必會(huì)造成線程阻塞,這就關(guān)系到Redis的性能了。

針對(duì)線程阻塞的問(wèn)題Redis提供了兩個(gè)命令,如下:

  1. 鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術(shù)社區(qū)

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

  3.  bgsave:fork一個(gè)子進(jìn)程,專門用于寫入RDB文件,避免了主線程的阻塞,這是Redis的默認(rèn)配置。

這樣就可以使用bgsave命令執(zhí)行全量快照,既可以保證數(shù)據(jù)的可靠性也避免了主線程的阻塞。

快照時(shí)能夠修改數(shù)據(jù)嗎?

子線程執(zhí)行全量快照的同時(shí),主線程仍然在接受著請(qǐng)求,讀數(shù)據(jù)肯定沒(méi)有問(wèn)題,但是如果個(gè)修改了數(shù)據(jù),如何能夠保證快照的完整性呢?

「舉個(gè)栗子」:我在T時(shí)刻進(jìn)行全量快照,假設(shè)數(shù)據(jù)量有8G,寫入磁盤的過(guò)程至少需要20S,在這20S的時(shí)間內(nèi),一旦內(nèi)存中的數(shù)據(jù)發(fā)生了修改,則快照的完整性就破壞了。

但是如果在快照時(shí)不能修改數(shù)據(jù),則對(duì)Redis的性能有巨大的影響,對(duì)于這個(gè)問(wèn)題,Redis是如何解決的呢?

?Redis借助操作系統(tǒng)提供的寫時(shí)復(fù)制技術(shù)(Copy-On-Write, COW),在執(zhí)行快照的同時(shí),正常處理寫操作。

其實(shí)很簡(jiǎn)單,bgsave命令會(huì)fork一個(gè)子線程,這個(gè)子線程共享所有內(nèi)存的數(shù)據(jù),子線程會(huì)讀取主線程內(nèi)存中的數(shù)據(jù),將他們寫入RDB文件。

Redis數(shù)據(jù)丟失如何解決

寫時(shí)復(fù)制保證數(shù)據(jù)可修改

如上圖,對(duì)于鍵值對(duì)A的讀取并不會(huì)影響子線程,但是如果主線程一旦修改內(nèi)存中一塊數(shù)據(jù)(例如鍵值對(duì)D),這塊數(shù)據(jù)將會(huì)被復(fù)制一個(gè)副本,然后bgsave子線程會(huì)將其寫入RDB文件。

多久做一次快照?

快照只是記錄某一時(shí)刻的數(shù)據(jù),一旦時(shí)間隔離很久,則服務(wù)器一旦宕機(jī),則會(huì)丟失那段時(shí)間的數(shù)據(jù)。

比如在T1時(shí)間做了一次快照,在T1+t時(shí)又做了一次快照,如果在t這個(gè)時(shí)間段內(nèi)服務(wù)器突然宕機(jī)了,則快照中只保存了T1時(shí)刻的快照,在t時(shí)間段內(nèi)的數(shù)據(jù)修改未被記錄(丟失)。如下圖:

Redis數(shù)據(jù)丟失如何解決

t時(shí)刻宕機(jī),未執(zhí)行快照

從上圖明顯可以看出,「RDB并不是一個(gè)完美的日志記錄方案」,只有讓t時(shí)間逐漸縮小,才能保證丟失的數(shù)據(jù)縮小。

「那么問(wèn)題來(lái)了,時(shí)間能夠縮短1秒嗎?」 即是每秒執(zhí)行一次快照。

?全量快照是記錄某一個(gè)時(shí)刻的「全部」內(nèi)存數(shù)據(jù),每秒執(zhí)行一次的對(duì)Redis性能影響巨大,于是「增量快照」就出來(lái)了。

增量快照

「增量快照是指做了一次全量快照之后,后續(xù)的快照只對(duì)修改的數(shù)據(jù)進(jìn)行快照記錄」,這樣可以避免每次都全量快照的開(kāi)銷。

增量快照的前提是Redis能夠記住修改的數(shù)據(jù),這個(gè)功能其實(shí)開(kāi)銷也是巨大的,需要保存完整的鍵值對(duì),這對(duì)內(nèi)存的消耗是巨大的。

?為了解決這個(gè)問(wèn)題,Redis使用了AOF和RDB混合使用的方式。

AOF和RDB混合使用

這個(gè)概念是在Redis4.0提出的,簡(jiǎn)單的說(shuō)就是「內(nèi)存快照以一定的頻率執(zhí)行,比如1小時(shí)一次,在兩次快照之間,使用AOF日志記錄這期間的所有命令操作?!?/p>

?混合使用的方式使得內(nèi)存快照不必頻繁的執(zhí)行,并且AOF記錄的也不是全部的操作命令,而是兩次快照之間的操作命令,不會(huì)出現(xiàn)AOF日志文件過(guò)大的情況了,避免了AOF重寫的開(kāi)銷了。

這個(gè)方案既能夠用到的RDB的快速恢復(fù)的好處,又能享受都只記錄操作命令的簡(jiǎn)單優(yōu)勢(shì),強(qiáng)烈建議使用。

總結(jié)

RDB內(nèi)存快照記錄的是某一個(gè)時(shí)刻的內(nèi)存數(shù)據(jù),因此能夠快速恢復(fù);AOF和RDB混合使用能夠使得宕機(jī)后數(shù)據(jù)快速恢復(fù),又能夠避免AOF日志文件過(guò)大。

總結(jié)

本文介紹了兩種數(shù)據(jù)恢復(fù)和持久化的方案,分別是AOF和RDB。

AOF介紹了什么?如下:

  1.  AOF是寫后日志,通過(guò)記錄操作命令持久化數(shù)據(jù)。

  2.  由于AOF是在命令執(zhí)行之后記錄日志,如果在寫入磁盤之前服務(wù)器宕機(jī),則會(huì)丟失數(shù)據(jù);如果寫入磁盤的時(shí)候突然阻塞,則會(huì)阻塞主線程;為了解決以上問(wèn)題,AOF機(jī)制提供了三種寫回的策略,每種策略都有不同的優(yōu)缺點(diǎn)。

  3.  AOF日志文件過(guò)大怎么辦?AOF通過(guò)fork一個(gè)子線程重寫一個(gè)新的日志文件(共享主線程的內(nèi)存,記錄最新數(shù)據(jù)的寫入命令),同時(shí)子線程重寫,避免阻塞主線程。

RDB介紹了什么?如下:

  1. 鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術(shù)社區(qū)

  2.  RDB是內(nèi)存快照,記錄某一個(gè)時(shí)刻的內(nèi)存數(shù)據(jù),而不是操作命令。

  3.  Redis提供了兩個(gè)命令,分別是save、bgsave來(lái)執(zhí)行全量快照,這兩個(gè)命令的區(qū)別則是save是在主線程執(zhí)行,勢(shì)必會(huì)阻塞主線程,bgsave是在fork一個(gè)子線程,共享內(nèi)存。

  4.  RDB通過(guò)操作系統(tǒng)的「寫時(shí)復(fù)制技術(shù)」,能夠保證在執(zhí)行快照的同時(shí)主線程能夠修改快照。

  5.  由于兩次快照之間是存在間隔的,一旦服務(wù)器宕機(jī),則會(huì)丟失兩次間隔時(shí)刻的數(shù)據(jù),Redis4.0開(kāi)始使用AOF日志記錄兩次快照之間執(zhí)行的命令(AOF和RDB混合使用)。 

關(guān)于Redis數(shù)據(jù)丟失如何解決就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向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