亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.430618.com 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

正文

對于一項技術的學習,我們要對這項技術有一個全局觀,下面是一張 redis 全景圖,我覺得畫得非常全面。

圖源:極客時間《Redis核心技術與實戰(zhàn)》-蔣德均

今天我們主要關注 Redis 的高可用主線。Redis 的高可用性,具體來說,有兩方面含義:一是服務少中斷,二是數(shù)據(jù)少丟失。

為了保證服務少中斷,通常的做法就是冗余,增加服務的副本,但是當副本多了以后,如何保證副本的數(shù)據(jù)一致就成了問題。

一、主從庫模式

在這方面,Redis 提供了主從庫模式,主從庫之間采用的是讀寫分離的方式:對于讀操作請求,主從庫都可以接收;對于寫操作,首先到主庫執(zhí)行,然后,主庫將寫操作同步給從庫。

Redis讀寫分離

那么,主從庫同步是如何完成的呢?主庫數(shù)據(jù)是一次性傳給從庫,還是分批同步?要是主從庫間的網絡斷連了,數(shù)據(jù)還能保持一致嗎?

1.1 數(shù)據(jù)同步的實現(xiàn)細節(jié)

當我們啟動多個 Redis 實例的時候,它們相互之間就可以通過 replicaof(Redis 5.0 之前使用 slaveof)命令形成主庫和從庫的關系。

例如,現(xiàn)在有實例 1(ip:172.16.19.3)和實例 2(ip:172.16.19.5),我們在實例 2 上執(zhí)行以下這個命令后,實例 2 就變成了實例 1 的從庫,并從實例 1 上復制數(shù)據(jù):

replicaof 172.16.19.3 6379

之后會按照三個階段完成數(shù)據(jù)的第一次同步。

第一階段:主從庫間建立連接、協(xié)商同步的過程,主要是為全量復制做準備。具體來說,從庫給主庫發(fā)送 psync 命令,表示要進行數(shù)據(jù)同步,主庫根據(jù)這個命令的參數(shù)來啟動復制。psync 命令包含了主庫的 runID 和復制進度 offset 兩個參數(shù)。runID,是每個 Redis 實例啟動時都會自動生成的一個隨機 ID,用來唯一標記這個實例。當從庫和主庫第一次復制時,因為不知道主庫的 runID,所以將 runID 設為“?”。offset,此時設為 -1,表示第一次復制。

主庫收到 psync 命令后,會用 FULLRESYNC 響應命令帶上兩個參數(shù):主庫 runID 和主庫目前的復制進度 offset(這個offset是當前最新的值),返回給從庫。從庫收到響應后,會記錄下這兩個參數(shù)。

第二階段:主庫將所有數(shù)據(jù)同步給從庫。具體來說,主庫執(zhí)行 bgsave 命令,生成 RDB 文件,接著將文件發(fā)給從庫。從庫接收到 RDB 文件后,會先清空當前數(shù)據(jù)庫,然后加載 RDB 文件。

為什么要先清空當前數(shù)據(jù)庫呢?這是因為從庫在通過 replicaof 命令開始和主庫同步前,可能保存了其他數(shù)據(jù)。為了避免之前數(shù)據(jù)的影響,從庫需要先把當前數(shù)據(jù)庫清空。

在主庫將數(shù)據(jù)同步給從庫的過程中,主庫不會被阻塞,仍然可以正常接收請求。否則,Redis 的服務就被中斷了。但是,這些請求中的寫操作并沒有記錄到剛剛生成的 RDB 文件中。為了保證主從庫的數(shù)據(jù)一致性,主庫會在內存中用專門的 replication buffer,記錄 RDB 文件生成后收到的所有寫操作。

第三階段:當主庫完成 RDB 文件發(fā)送后,就會把此時 replication buffer 中的修改操作發(fā)給從庫,從庫再重新執(zhí)行這些操作。

主從復制整個過程示意圖如下所示。

主從庫第一次同步的三個階段

這樣一來,主從庫就實現(xiàn)同步了。不可忽視的是,這個過程中存在著風險點,最常見的就是網絡斷連或阻塞。如果網絡斷連,主從庫之間就無法進行命令傳播了,從庫的數(shù)據(jù)自然也就沒辦法和主庫保持一致了,客戶端就可能從從庫讀到舊數(shù)據(jù)。

1.2 主從庫間網絡斷了怎么辦?

在 Redis 2.8 之前,如果主從庫在命令傳播時出現(xiàn)了網絡閃斷,那么,從庫就會和主庫重新進行一次全量復制,開銷非常大。從 Redis 2.8 開始,網絡斷了之后,主從庫會采用增量復制的方式繼續(xù)同步。只把主從庫網絡斷連期間主庫收到的命令,同步給從庫。

當主從庫斷連后,主庫會把斷連期間收到的寫操作命令,寫入 replication buffer,同時也會把這些操作命令寫入 repl_backlog_buffer 這個緩沖區(qū)。repl_backlog_buffer 是一個環(huán)形緩沖區(qū),主庫會記錄自己寫到的位置,從庫則會記錄自己已經讀到的位置。

在網絡斷連階段,主庫可能會收到新的寫操作命令,所以,一般來說,主庫寫到的位置會大于從庫讀到的位置。當網絡恢復后,主庫只用把主庫寫到的位置和從庫讀到的位置之間的命令操作同步給從庫就行。

repl_backlog_buffer示意圖

Redis 通過主從庫模式,既提高了系統(tǒng)處理請求的吞吐量,也保證了系統(tǒng)的可用性。

如果從庫發(fā)生故障了,客戶端可以繼續(xù)向主庫或其他從庫發(fā)送請求,進行相關的操作。但是如果主庫發(fā)生故障了怎么辦?此時從庫沒有相應的主庫可以進行數(shù)據(jù)復制操作了,且一旦有寫操作請求,系統(tǒng)也將無法處理。

二、哨兵機制

所以,如果主庫掛了,我們就需要運行一個新主庫,比如說把一個從庫切換為主庫,把它當成主庫。在 Redis 主從集群中,哨兵機制是實現(xiàn)主從庫自動切換的關鍵機制。

Redis哨兵機制

2.1 哨兵的職責

哨兵其實就是一個運行在特殊模式下的 Redis 進程,主從庫實例運行的同時,它也在運行。哨兵主要負責的就是三個任務:監(jiān)控、選主(選擇主庫)和通知。

哨兵的職責

監(jiān)控是指哨兵進程在運行時,周期性地給所有的主從庫發(fā)送 PING 命令,檢測它們是否仍然在線運行。如果從庫沒有在規(guī)定時間內響應哨兵的 PING 命令,哨兵就會把它標記為“下線狀態(tài)”;同樣,如果主庫也沒有在規(guī)定時間內響應哨兵的 PING 命令,哨兵就會判定主庫下線,然后開始自動切換主庫的流程。

選主是指主庫掛了以后,哨兵就需要從很多個從庫里,按照一定的規(guī)則選擇一個從庫實例,把它作為新的主庫。這一步完成后,現(xiàn)在的集群里就有了新主庫。

然后,哨兵會執(zhí)行最后一個任務:通知。在執(zhí)行通知任務時,哨兵會把新主庫的連接信息發(fā)給其他從庫,讓它們執(zhí)行 replicaof 命令,和新主庫建立連接,并進行數(shù)據(jù)復制。同時,哨兵會把新主庫的連接信息通知給客戶端,讓它們把請求操作發(fā)到新主庫上。

但是你有沒有想過,如果有哨兵實例在運行時發(fā)生了故障,主從庫還能正常切換嗎?

2.2 哨兵的高可用

哨兵單點故障問題,Redis 也是通過建立哨兵集群來解決的。那我們再回頭看哨兵的職責,在監(jiān)控主從庫是否下線時,如果出現(xiàn)了哨兵內部的意見不統(tǒng)一怎么辦?比如說有 3 個哨兵,其中一個哨兵認為主庫下線了,而另外 2 個卻認為主庫是正常的,這時該聽誰的呢?

這就好比我們團隊內部出現(xiàn)了意見分歧,那最好的解決辦法就是民主投票了,采用“少數(shù)服從多數(shù)的原則”。哨兵集群內部也一樣,在網絡擁塞的情況下,有個別哨兵與主庫的 PING 命令失敗,這時哨兵就認為該主庫故障了,然而實際并沒有。這時就要采用“民主”的辦法,大多數(shù)哨兵認為主庫故障,才會進行下一步的選主。

哨兵的實例數(shù)應該是 2N+1 的單數(shù),這樣才不致于出現(xiàn)觀點對立的情況,通常我們至少會配置 3 個哨兵實例。

那選主同樣需要考慮一個問題:哨兵這么多,該由哪個執(zhí)行主從切換?

此時,這個哨兵就可以再給其他哨兵發(fā)送命令,表明希望由自己來執(zhí)行主從切換,并讓所有其他哨兵進行投票。這個投票過程稱為“Leader 選舉”。因為最終執(zhí)行主從切換的哨兵稱為 Leader,投票過程就是確定 Leader。

到這里,我們就大致理清了 Redis 保證服務少中斷所采取的一系列方案了。那 Redis 是如何保證數(shù)據(jù)少丟失的呢?

三、AOF和RDB

了解 MySQL 的同學可能聽說過,MySQL 是具有 Crasf-Safe 的能力的,這歸功于數(shù)據(jù)庫的寫前日志(Write Ahead Log, WAL) Redo Log。同樣,Redis 也提供了 AOF 日志。

3.1 主庫宕機了,如何避免數(shù)據(jù)丟失?

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

AOF日志內容

但是,因為記錄的是操作命令,而不是實際的數(shù)據(jù),所以,用 AOF 方法進行故障恢復的時候,需要逐一把操作日志都執(zhí)行一遍。如果操作日志非常多,Redis 就會恢復得很緩慢,影響到正常使用。

因此,Redis 提供了另一種數(shù)據(jù)持久化方法:內存快照 RDB。和 AOF 相比,RDB 記錄的是某一時刻的數(shù)據(jù),并不是操作,所以,在做數(shù)據(jù)恢復時,我們可以直接把 RDB 文件讀入內存,很快地完成恢復。

對于快照來說,系統(tǒng)多久執(zhí)行一次快照直接影響數(shù)據(jù)丟失的多少。如下圖所示,我們先在 T0 時刻做了一次快照,然后又在 T0+t 時刻做了一次快照,在這期間,數(shù)據(jù)塊 5 和 9 被修改了。如果在 t 這段時間內,機器宕機了,那么,只能按照 T0 時刻的快照進行恢復。此時,數(shù)據(jù)塊 5 和 9 的修改值因為沒有快照記錄,就無法恢復了。

RDB數(shù)據(jù)丟失

所以,要想盡可能恢復數(shù)據(jù),t 值就要盡可能小。那么,t 值可以小到什么程度呢,比如說是不是可以每秒做一次快照?

3.2 宕機后,如何快速恢復數(shù)據(jù)?

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

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

RDB與AOF混合使用

這個方法既能享受到 RDB 文件快速恢復的好處,又能享受到 AOF 只記錄操作命令的簡單優(yōu)勢。

小結

我來總結一下本文的內容。Redis 系統(tǒng)的高可用,具體可以通過兩個方面來理解:一是服務少中斷,二是數(shù)據(jù)少丟失。我整理的知識消化鏈路如下。

服務少中斷 -> 多副本 -> 主從庫模式保證數(shù)據(jù)一致及從庫的高可用 -> 哨兵保證主庫的高可用 -> 哨兵集群保證哨兵高可用。
數(shù)據(jù)少丟失 -> AOF日志 -> AOF恢復數(shù)據(jù)較慢 -> RDB內存快照 -> 執(zhí)行快照間隔不宜過短 -> AOF+RDB

關于哨兵機制的更多實現(xiàn)細節(jié),我會在后面的內容里繼續(xù)更新,敬請關注。公眾號「楊同學technotes」,歡迎技術交流。

分享到:
標簽:Redis
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數(shù)獨大挑戰(zhàn)2018-06-03

數(shù)獨一種數(shù)學游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數(shù)有氧達人2018-06-03

記錄運動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定