偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Redis宕機(jī)后,Redis如何實(shí)現(xiàn)快速恢復(fù)?

數(shù)據(jù)庫 Redis
在本篇文章中,我們深入學(xué)習(xí)了Redis用于避免數(shù)據(jù)丟失的內(nèi)存快照方法。這種持久化方式具有快速恢復(fù)數(shù)據(jù)庫的顯著優(yōu)勢,只需將RDB文件直接加載到內(nèi)存中,避免了AOF方式需要逐一重新執(zhí)行操作命令所帶來的性能低效問題。

當(dāng)前,我們已經(jīng)深入了解了Redis中的AOF(Append-Only File)持久化方法,它的優(yōu)勢在于記錄操作命令,不會(huì)顯著增加持久化數(shù)據(jù)量。通常情況下,只要你沒有選擇always的持久化策略,AOF方法對性能的影響是相對較小的。

然而,由于AOF方法記錄的是操作命令而不是實(shí)際的數(shù)據(jù),所以在使用AOF進(jìn)行故障恢復(fù)時(shí),需要逐一執(zhí)行所有的操作日志。當(dāng)操作日志非常龐大時(shí),這個(gè)恢復(fù)過程會(huì)變得非常緩慢,從而影響了正常的使用體驗(yàn)。顯然,這并不是我們理想的情況。那么,是否有其他方法既可以保障數(shù)據(jù)可靠性,又能在宕機(jī)后實(shí)現(xiàn)快速恢復(fù)呢?

當(dāng)然有,這就是我們今天要一同探討的另一種持久化方法:內(nèi)存快照。內(nèi)存快照的概念很像拍照,它記錄了某一時(shí)刻的內(nèi)存中數(shù)據(jù)狀態(tài),就像照片一樣。當(dāng)你給朋友拍照時(shí),一張照片能完美地捕捉朋友的瞬間。對于Redis,它通過將某一時(shí)刻的數(shù)據(jù)狀態(tài)以文件形式寫入磁盤來實(shí)現(xiàn)這種效果,這個(gè)文件就是快照,通常稱為RDB文件,其中RDB代表Redis數(shù)據(jù)庫。

RDB文件的優(yōu)勢在于,即使發(fā)生宕機(jī),快照文件也不會(huì)丟失,因此可靠性得到了保證。接下來,我們將深入了解RDB持久化方法,包括它的工作原理和配置等方面的細(xì)節(jié)。這將有助于你更好地理解如何選擇適當(dāng)?shù)某志没椒?,以滿足你的特定需求。

與AOF持久化相比,RDB持久化記錄的是某一時(shí)刻的數(shù)據(jù)狀態(tài),而不是每個(gè)操作命令。這意味著在數(shù)據(jù)恢復(fù)過程中,我們可以直接將RDB文件加載到內(nèi)存中,迅速完成恢復(fù)。聽起來似乎非常理想,但內(nèi)存快照也并不是毫無缺點(diǎn)的最佳選項(xiàng)。為什么會(huì)這樣呢?

我們需要考慮兩個(gè)關(guān)鍵問題:

  1. 哪些數(shù)據(jù)進(jìn)行快照?這關(guān)系到快照執(zhí)行的效率問題。
  2. 在進(jìn)行快照時(shí),數(shù)據(jù)是否能夠被修改、新增或刪除?這關(guān)系到Redis是否會(huì)被阻塞,以及是否能夠同時(shí)處理其他請求。

這或許還不夠清晰,我來用拍照的例子進(jìn)行解釋。當(dāng)我們拍照時(shí),通常要思考兩個(gè)問題:

  • 如何構(gòu)圖?也就是我們打算在照片中捕捉哪些人或物體。
  • 在按下快門之前,需要確保拍攝對象不亂動(dòng),以避免照片模糊。

你可以看到,這兩個(gè)問題非常重要,接下來,我們將詳細(xì)討論這兩個(gè)問題,首先是“構(gòu)圖”問題,即我們應(yīng)該選擇哪些數(shù)據(jù)進(jìn)行快照。

給哪些內(nèi)存數(shù)據(jù)做快照?

Redis 的數(shù)據(jù)都在內(nèi)存中,為了提供所有數(shù)據(jù)的可靠性保證,它執(zhí)行的是全量快照,也就是說,把內(nèi)存中的所有數(shù)據(jù)都記錄到磁盤中,這就類似于給 100 個(gè)人拍合影,把每一個(gè)人都拍進(jìn)照片里。這樣做的好處是,一次性記錄了所有數(shù)據(jù),一個(gè)都不少。

當(dāng)你給一個(gè)人拍照時(shí),只用協(xié)調(diào)一個(gè)人就夠了,但是,拍 100 人的大合影,卻需要協(xié)調(diào) 100 個(gè)人的位置、狀態(tài),等等,這當(dāng)然會(huì)更費(fèi)時(shí)費(fèi)力。同樣,給內(nèi)存的全量數(shù)據(jù)做快照,把它們?nèi)繉懭氪疟P也會(huì)花費(fèi)很多時(shí)間。而且,全量數(shù)據(jù)越多,RDB 文件就越大,往磁盤上寫數(shù)據(jù)的時(shí)間開銷就越大。

對于 Redis 而言,它的單線程模型就決定了,我們要盡量避免所有會(huì)阻塞主線程的操作,所以,針對任何操作,我們都會(huì)提一個(gè)靈魂之問:“它會(huì)阻塞主線程嗎?”RDB 文件的生成是否會(huì)阻塞主線程,這就關(guān)系到是否會(huì)降低 Redis 的性能。

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

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

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

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

接下來,我們要關(guān)注的問題就是,在對內(nèi)存數(shù)據(jù)做快照時(shí),這些數(shù)據(jù)還能“動(dòng)”嗎? 也就是說,這些數(shù)據(jù)還能被修改嗎?這個(gè)問題非常重要,這是因?yàn)椋绻麛?shù)據(jù)能被修改,那就意味著 Redis 還能正常處理寫操作。否則,所有寫操作都得等到快照完了才能執(zhí)行,性能一下子就降低了。

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

在給別人拍照時(shí),一旦對方動(dòng)了,那么這張照片就拍糊了,我們就需要重拍,所以我們當(dāng)然希望對方保持不動(dòng)。對于內(nèi)存快照而言,我們也不希望數(shù)據(jù)“動(dòng)”。

舉個(gè)例子。我們在時(shí)刻 t 給內(nèi)存做快照,假設(shè)內(nèi)存數(shù)據(jù)量是 4GB,磁盤的寫入帶寬是 0.2GB/s,簡單來說,至少需要 20s(4/0.2 = 20)才能做完。如果在時(shí)刻 t+5s 時(shí),一個(gè)還沒有被寫入磁盤的內(nèi)存數(shù)據(jù) A,被修改成了 A’,那么就會(huì)破壞快照的完整性,因?yàn)?A’不是時(shí)刻 t 時(shí)的狀態(tài)。因此,和拍照類似,我們在做快照時(shí)也不希望數(shù)據(jù)“動(dòng)”,也就是不能被修改。

但是,如果快照執(zhí)行期間數(shù)據(jù)不能被修改,是會(huì)有潛在問題的。對于剛剛的例子來說,在做快照的 20s 時(shí)間里,如果這 4GB 的數(shù)據(jù)都不能被修改,Redis 就不能處理對這些數(shù)據(jù)的寫操作,那無疑就會(huì)給業(yè)務(wù)服務(wù)造成巨大的影響。

你可能會(huì)想到,可以用 bgsave 避免阻塞啊。這里我就要說到一個(gè)常見的誤區(qū)了,避免阻塞和正常處理寫操作并不是一回事。此時(shí),主線程的確沒有阻塞,可以正常接收請求,但是,為了保證快照完整性,它只能處理讀操作,因?yàn)椴荒苄薷恼趫?zhí)行快照的數(shù)據(jù)。

為了快照而暫停寫操作,肯定是不能接受的。所以這個(gè)時(shí)候,Redis 就會(huì)借助操作系統(tǒng)提供的寫時(shí)復(fù)制技術(shù)(Copy-On-Write, COW),在執(zhí)行快照的同時(shí),正常處理寫操作。

簡單來說,bgsave 子進(jìn)程是由主線程 fork 生成的,可以共享主線程的所有內(nèi)存數(shù)據(jù)。bgsave 子進(jìn)程運(yùn)行后,開始讀取主線程的內(nèi)存數(shù)據(jù),并把它們寫入 RDB 文件。

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

圖片

寫時(shí)復(fù)制機(jī)制保證快照期間數(shù)據(jù)可修改

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

到這里,我們就解決了對“哪些數(shù)據(jù)做快照”以及“做快照時(shí)數(shù)據(jù)能否修改”這兩大問題:Redis 會(huì)使用 bgsave 對當(dāng)前內(nèi)存中的所有數(shù)據(jù)做快照,這個(gè)操作是子進(jìn)程在后臺完成的,這就允許主線程同時(shí)可以修改數(shù)據(jù)。

現(xiàn)在,我們再來看另一個(gè)問題:多久做一次快照?我們在拍照的時(shí)候,還有項(xiàng)技術(shù)叫“連拍”,可以記錄人或物連續(xù)多個(gè)瞬間的狀態(tài)。那么,快照也適合“連拍”嗎?

可以每秒做一次快照嗎?

對于內(nèi)存快照,所謂的“連拍”即連續(xù)執(zhí)行多次快照。這將大大減小快照之間的時(shí)間間隔,即使在某一刻發(fā)生宕機(jī),由于上一刻的快照剛剛執(zhí)行,所丟失的數(shù)據(jù)也會(huì)降至最低。然而,快照間隔時(shí)間的選擇成為關(guān)鍵。

如下圖所示,我們在T0時(shí)刻首次執(zhí)行了一次快照,然后在T0+t時(shí)刻再次執(zhí)行了快照。在這段時(shí)間內(nèi),數(shù)據(jù)塊5和9發(fā)生了修改。如果在t時(shí)間內(nèi)出現(xiàn)宕機(jī),只能按照T0時(shí)刻的快照進(jìn)行恢復(fù)。這時(shí),由于數(shù)據(jù)塊5和9的修改沒有被記錄在快照中,它們的值將無法完全恢復(fù)。


圖片

快照機(jī)制下的數(shù)據(jù)丟失

所以,要想盡可能恢復(fù)數(shù)據(jù),t 值就要盡可能小,t 越小,就越像“連拍”。那么,t 值可以小到什么程度呢,比如說是不是可以每秒做一次快照?畢竟,每次快照都是由 bgsave 子進(jìn)程在后臺執(zhí)行,也不會(huì)阻塞主線程。

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

首先,頻繁將完整的數(shù)據(jù)寫入磁盤會(huì)對磁盤造成巨大的壓力。多個(gè)快照爭相使用有限的磁盤帶寬,這可能導(dǎo)致前一個(gè)快照尚未完成,后一個(gè)快照已經(jīng)開始,從而產(chǎn)生惡性循環(huán)。

另一方面,bgsave子進(jìn)程需要通過fork操作從主線程中創(chuàng)建。雖然子進(jìn)程在創(chuàng)建后不會(huì)再次阻塞主線程,但是fork這個(gè)創(chuàng)建過程本身會(huì)阻塞主線程。而且主線程的內(nèi)存越大,阻塞時(shí)間越長。如果頻繁進(jìn)行fork以創(chuàng)建bgsave子進(jìn)程,這將頻繁地阻塞主線程。那么,有沒有更好的方法呢?

在這種情況下,可以考慮使用增量快照。增量快照指的是在生成完整快照后,后續(xù)的快照只記錄已更改的數(shù)據(jù),從而避免每次生成完整快照的開銷。

在第一次做完全量快照后,T1 和 T2 時(shí)刻如果再做快照,我們只需要將被修改的數(shù)據(jù)寫入快照文件就行。但是,這么做的前提是,我們需要記住哪些數(shù)據(jù)被修改了。你可不要小瞧這個(gè)“記住”功能,它需要我們使用額外的元數(shù)據(jù)信息去記錄哪些數(shù)據(jù)被修改了,這會(huì)帶來額外的空間開銷問題。如下圖所示:

圖片

增量快照示意圖

如果我們?yōu)槊總€(gè)鍵值對的修改都記錄一條記錄,那么當(dāng)有1萬個(gè)鍵值對被修改時(shí),我們就需要額外記錄1萬條記錄。有時(shí),鍵值對可能非常小,例如只有32字節(jié),而為了記錄它們的修改,我們可能需要8字節(jié)的元數(shù)據(jù)信息。在某些情況下,為了記錄修改所引入的額外空間開銷會(huì)相當(dāng)大。對于內(nèi)存資源寶貴的Redis來說,這可能不是一個(gè)劃算的選擇。

從這里可以看出,雖然與AOF相比,快照的恢復(fù)速度更快,但快照的頻率很難確定。如果頻率太低,一旦在兩次快照之間發(fā)生宕機(jī),可能會(huì)有大量數(shù)據(jù)丟失。如果頻率太高,將導(dǎo)致額外的開銷。那么,有沒有一種方法既能利用RDB的快速恢復(fù),又能以較小的開銷盡量減少數(shù)據(jù)丟失呢?

Redis 4.0 中提出了一個(gè)混合使用 AOF 日志和內(nèi)存快照的方法。簡單來說,內(nèi)存快照以一定的頻率執(zhí)行,在兩次快照之間,使用 AOF 日志記錄這期間的所有命令操作。

這樣一來,快照不用很頻繁地執(zhí)行,這就避免了頻繁 fork 對主線程的影響。而且,AOF 日志也只用記錄兩次快照間的操作,也就是說,不需要記錄所有操作了,因此,就不會(huì)出現(xiàn)文件過大的情況了,也可以避免重寫開銷。

如下圖所示,T1 和 T2 時(shí)刻的修改,用 AOF 日志記錄,等到第二次做全量快照時(shí),就可以清空 AOF 日志,因?yàn)榇藭r(shí)的修改都已經(jīng)記錄到快照中了,恢復(fù)時(shí)就不再用日志了。

圖片

內(nèi)存快照和AOF混合使用

這個(gè)方法既能享受到 RDB 文件快速恢復(fù)的好處,又能享受到 AOF 只記錄操作命令的簡單優(yōu)勢,頗有點(diǎn)“魚和熊掌可以兼得”的感覺,建議你在實(shí)踐中用起來。

小結(jié)

在本篇文章中,我們深入學(xué)習(xí)了Redis用于避免數(shù)據(jù)丟失的內(nèi)存快照方法。這種持久化方式具有快速恢復(fù)數(shù)據(jù)庫的顯著優(yōu)勢,只需將RDB文件直接加載到內(nèi)存中,避免了AOF方式需要逐一重新執(zhí)行操作命令所帶來的性能低效問題。

然而,內(nèi)存快照方法也存在一些限制。它類似于拍攝內(nèi)存的“大合影”,這不可避免地會(huì)占用較多的時(shí)間和計(jì)算資源。雖然Redis采用了bgsave和寫時(shí)復(fù)制等方式來最小化內(nèi)存快照對正常讀寫操作的影響,但頻繁的快照仍然可能對性能產(chǎn)生不可接受的壓力。因此,將RDB和AOF方式混合使用,可以充分利用它們各自的優(yōu)勢,規(guī)避它們的弱點(diǎn),以較小的性能開銷來同時(shí)保證數(shù)據(jù)的可靠性和性能。

最后,關(guān)于選擇AOF和RDB的問題,我愿意提供三點(diǎn)建議:

  1. 當(dāng)數(shù)據(jù)絕不能丟失時(shí),混合使用內(nèi)存快照和AOF方式是一個(gè)明智的選擇。
  2. 如果可以容忍分鐘級別的數(shù)據(jù)丟失,可以只使用RDB方式。
  3. 如果決定僅采用AOF方式,首選使用everysec的配置選項(xiàng),因?yàn)樗诳煽啃院托阅苤g取得了較好的平衡。
責(zé)任編輯:武曉燕 來源: 碼農(nóng)本農(nóng)
相關(guān)推薦

2021-03-18 10:31:27

Redis宕機(jī)日志

2021-02-22 09:01:13

Redis宕機(jī)日志

2023-10-23 11:22:06

Redis數(shù)據(jù)持久化

2025-06-30 03:25:00

2020-07-14 11:00:12

Spring BootRedisJava

2021-11-30 06:32:19

Redis宕機(jī)集群

2017-05-31 16:10:45

MySQL誤操作恢復(fù)數(shù)據(jù)

2020-03-31 17:05:39

Redis熱 key代理

2016-04-19 18:20:29

阿里巴巴HBase宕機(jī)恢復(fù)

2015-10-29 15:36:19

Redis入門

2020-12-31 07:34:04

Redis數(shù)據(jù)宕機(jī)

2020-09-02 17:28:26

Spring Boot Redis集成

2021-01-05 10:48:38

RedisAOF日志RDB快照

2018-07-24 16:40:29

MySQL主從架構(gòu)主庫宕機(jī)

2024-12-17 15:39:33

2018-11-01 14:50:01

RedisNoSQL數(shù)據(jù)庫

2024-03-22 12:10:39

Redis消息隊(duì)列數(shù)據(jù)庫

2015-06-29 11:29:08

2020-11-25 08:57:29

Redis Docke

2024-11-04 16:01:01

點(diǎn)贊
收藏

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