<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Redis高可用總結(jié):Redis主從復(fù)制、哨兵集群、腦裂...

          共 4995字,需瀏覽 10分鐘

           ·

          2021-01-26 14:31

          作者:Ccww
          來(lái)源:SegmentFault 思否社區(qū)




          在實(shí)際的項(xiàng)目中,服務(wù)高可用非常重要,如,當(dāng)Redis作為緩存服務(wù)使用時(shí), 緩解數(shù)據(jù)庫(kù)的壓力,提高數(shù)據(jù)的訪(fǎng)問(wèn)速度,提高網(wǎng)站的性能 ,但如果使用Redis 是單機(jī)模式運(yùn)行 ,只要一個(gè)服務(wù)器宕機(jī)就不可以提供服務(wù),這樣會(huì)可能造成服務(wù)效率低下,甚至出現(xiàn)其相對(duì)應(yīng)的服務(wù)應(yīng)用不可用。


          因此為了實(shí)現(xiàn)高可用,Redis 提供了哪些高可用方案?


          • Redis主從復(fù)制
          • Redis持久化
          • 哨兵集群
          • ...


          Redis基于一個(gè)Master主節(jié)點(diǎn)多Slave從節(jié)點(diǎn)的模式和Redis持久化機(jī)制,將一份數(shù)據(jù)保持在多個(gè)實(shí)例中實(shí)現(xiàn)增加副本冗余量,又使用哨兵機(jī)制實(shí)現(xiàn)主備切換, 在master故障時(shí),自動(dòng)檢測(cè),將某個(gè)slave切換為master,最終實(shí)現(xiàn)Redis高可用 。



          Redis主從復(fù)制


          Redis主從復(fù)制,主從庫(kù)模式一個(gè)Master主節(jié)點(diǎn)多Slave從節(jié)點(diǎn)的模式,將一份數(shù)據(jù)保存在多Slave個(gè)實(shí)例中,增加副本冗余量,當(dāng)某些出現(xiàn)宕機(jī)后,Redis服務(wù)還可以使用。


          但是這會(huì)存在數(shù)據(jù)不一致問(wèn)題,那redis的副本集是如何數(shù)據(jù)一致性?

          Redis為了保證數(shù)據(jù)副本的一致,主從庫(kù)之間采用讀寫(xiě)分離的方式:

          • 讀操作:主庫(kù)、從庫(kù)都可以執(zhí)行處理;
          • 寫(xiě)操作:先在主庫(kù)執(zhí)行,再由主庫(kù)將寫(xiě)操作同步給從庫(kù)。

          使用讀寫(xiě)分離方式的好處,可以避免當(dāng)主從庫(kù)都可以處理寫(xiě)操作時(shí),主從庫(kù)處理寫(xiě)操作加鎖等一系列巨額的開(kāi)銷(xiāo)。

          采用讀寫(xiě)分離方式,寫(xiě)操作只會(huì)在主庫(kù)中進(jìn)行后同步到從庫(kù)中,那主從庫(kù)是如何同步數(shù)據(jù)的呢?

          主從庫(kù)是同步數(shù)據(jù)方式有兩種:

          • 全量同步:通常是主從服務(wù)器剛剛連接的時(shí)候,會(huì)先進(jìn)行全量同步
          • 增量同步?:一般在全同步結(jié)束后,進(jìn)行增量同步,比如主從庫(kù)間網(wǎng)絡(luò)斷,再進(jìn)行數(shù)據(jù)同步。


          全量同步


          主從庫(kù)間第一次全量同步,具體分成三個(gè)階段:

          • 當(dāng)一個(gè)從庫(kù)啟動(dòng)時(shí),從庫(kù)給主庫(kù)發(fā)送 psync 命令進(jìn)行數(shù)據(jù)同步(psync 命令包含:主庫(kù)的 runID 和復(fù)制進(jìn)度 offset 兩個(gè)參數(shù)),
          • 當(dāng)主庫(kù)接收到psync 命令后將會(huì)保存RDB 文件并發(fā)送給從庫(kù),發(fā)送期間會(huì)使用緩存區(qū)(replication buffer)記錄后續(xù)的所有寫(xiě)操作 ,從庫(kù)收到數(shù)據(jù)后,會(huì)先清空當(dāng)前數(shù)據(jù)庫(kù),然后加載從主庫(kù)獲取的RDB 文件,
          • 當(dāng)主庫(kù)完成 RDB 文件發(fā)送后,也會(huì)把將保存發(fā)送RDB文件期間寫(xiě)操作的replication buffer發(fā)給從庫(kù),從庫(kù)再重新執(zhí)行這些操作。這樣一來(lái),主從庫(kù)就實(shí)現(xiàn)同步了。


          另外,為了分擔(dān)主庫(kù)生成 RDB 文件和傳輸 RDB 文件壓力,提高效率,可以使用?“主 - 從 - 從”模式將主庫(kù)生成 RDB 和傳輸 RDB 的壓力,以級(jí)聯(lián)的方式分散到從庫(kù)上。


          增量同步


          增量同步,基于環(huán)形緩沖區(qū)repl_backlog_buffer緩存區(qū)實(shí)現(xiàn)。

          在環(huán)形緩沖區(qū),主庫(kù)會(huì)記錄自己寫(xiě)到的位置 master_repl_offset ,從庫(kù)則會(huì)記錄自己已經(jīng)讀到的位置slave_repl_offset, 主庫(kù)并通過(guò)master_repl_offset 和 slave_repl_offset的差值的數(shù)據(jù)同步到從庫(kù)。


          主從庫(kù)間網(wǎng)絡(luò)斷了, 主從庫(kù)會(huì)采用增量復(fù)制的方式繼續(xù)同步,主庫(kù)會(huì)把斷連期間收到的寫(xiě)操作命令,寫(xiě)入 replication buffer,同時(shí)也會(huì)把這些操作命令也寫(xiě)入 repl_backlog_buffer 這個(gè)緩沖區(qū),然后主庫(kù)并通過(guò)master_repl_offset 和 slave_repl_offset的差值數(shù)據(jù)同步到從庫(kù)。


          因?yàn)閞epl_backlog_buffer 是一個(gè)環(huán)形緩沖區(qū),當(dāng)在緩沖區(qū)寫(xiě)滿(mǎn)后,主庫(kù)會(huì)繼續(xù)寫(xiě)入,此時(shí),會(huì)出現(xiàn)什么情況呢?

          覆蓋掉之前寫(xiě)入的操作。如果從庫(kù)的讀取速度比較慢,就有可能導(dǎo)致從庫(kù)還未讀取的操作被主庫(kù)新寫(xiě)的操作覆蓋了,這會(huì)導(dǎo)致主從庫(kù)間的數(shù)據(jù)不一致。因此需要關(guān)注 repl_backlog_size參數(shù),調(diào)整合適的緩沖空間大小,避免數(shù)據(jù)覆蓋,主從數(shù)據(jù)不一致。

          主從復(fù)制,除了會(huì)出現(xiàn)數(shù)據(jù)不一致外,甚至可能出現(xiàn)主庫(kù)宕機(jī)的情況,Redis會(huì)有主從自主切換機(jī)制,那如何實(shí)現(xiàn)的呢?



          Redis哨兵機(jī)制


          當(dāng)主庫(kù)掛了,redis寫(xiě)操作和數(shù)據(jù)同步無(wú)法進(jìn)行,為了避免這樣情況,可以在主庫(kù)掛了后重新在從庫(kù)中選舉出一個(gè)新主庫(kù),并通知到客戶(hù)端,redis提供了?哨兵機(jī)制,哨兵為運(yùn)行在特殊模式下的 Redis 進(jìn)程。

          Redis會(huì)有主從自主切換機(jī)制,那如何實(shí)現(xiàn)的呢?


          哨兵機(jī)制是實(shí)現(xiàn)主從庫(kù)自動(dòng)切換的關(guān)鍵機(jī)制,其主要分為三個(gè)階段:

          • 監(jiān)控:哨兵進(jìn)程會(huì)周期性地給所有的主從庫(kù)發(fā)送 PING 命令,檢測(cè)它們是否仍然在線(xiàn)運(yùn)行。
          • 選主(選擇主庫(kù)):主庫(kù)掛了以后,哨兵基于一定規(guī)則評(píng)分選選舉出一個(gè)從庫(kù)實(shí)例新的主庫(kù) 。
          • 通知 :哨兵會(huì)將新主庫(kù)的信息發(fā)送給其他從庫(kù),讓它們和新主庫(kù)建立連接,并進(jìn)行數(shù)據(jù)復(fù)制。同時(shí),哨兵會(huì)把新主庫(kù)的信息廣播通知給客戶(hù)端,讓它們把請(qǐng)求操作發(fā)到新主庫(kù)上。


          其中,在監(jiān)控中如何判斷主庫(kù)是否處于下線(xiàn)狀態(tài)?

          哨兵對(duì)主庫(kù)的下線(xiàn)判斷分為:

          • 主觀下線(xiàn):哨兵進(jìn)程會(huì)使用 PING 命令檢測(cè)它自己和主、從庫(kù)的網(wǎng)絡(luò)連接情況,用來(lái)判斷實(shí)例的狀態(tài),?如果單哨兵發(fā)現(xiàn)主庫(kù)或從庫(kù)對(duì) PING 命令的響應(yīng)超時(shí)了,那么,哨兵就會(huì)先把它標(biāo)記為“主觀下線(xiàn)”
          • 客觀下線(xiàn):在哨兵集群中,基于少數(shù)服從多數(shù),多數(shù)實(shí)例都判定主庫(kù)已“主觀下線(xiàn)”,則認(rèn)為主庫(kù)“客觀下線(xiàn)”。

          為什么會(huì)有這兩種"主觀下線(xiàn)"和“客觀下線(xiàn)”的下線(xiàn)狀態(tài)呢?

          由于單機(jī)哨兵很容易產(chǎn)生誤判,誤判后主從切換會(huì)產(chǎn)生一系列的額外開(kāi)銷(xiāo),為了減少誤判,避免這些不必要的開(kāi)銷(xiāo),采用哨兵集群,引入多個(gè)哨兵實(shí)例一起來(lái)判斷,就可以避免單個(gè)哨兵因?yàn)樽陨砭W(wǎng)絡(luò)狀況不好,而誤判主庫(kù)下線(xiàn)的情況,

          基于少數(shù)服從多數(shù)原則, 當(dāng)有 N 個(gè)哨兵實(shí)例時(shí),最好要有 N/2 + 1 個(gè)實(shí)例判斷主庫(kù)為“主觀下線(xiàn)”,才能最終判定主庫(kù)為“客觀下線(xiàn)” (可以自定義設(shè)置闕值)。


          那么哨兵之間是如何互相通信的呢?

          哨兵集群中哨兵實(shí)例之間可以相互發(fā)現(xiàn),基于?Redis?提供的發(fā)布 / 訂閱機(jī)制(pub/sub?機(jī)制),

          哨兵可以在主庫(kù)中發(fā)布/訂閱消息,在主庫(kù)上有一個(gè)名為“\__sentinel__:hello”的頻道,不同哨兵就是通過(guò)它來(lái)相互發(fā)現(xiàn),實(shí)現(xiàn)互相通信的,而且只有訂閱了同一個(gè)頻道的應(yīng)用,才能通過(guò)發(fā)布的消息進(jìn)行信息交換。


          哨兵 1連接相關(guān)信息(IP端口)發(fā)布到“\__sentinel__:hello”頻道上,哨兵 2 和 3 訂閱了該頻道。

          哨兵 2 和 3 就可以從這個(gè)頻道直接獲取哨兵 1連接信息,以這樣的方式哨兵集群就形成了,實(shí)現(xiàn)各個(gè)哨兵互相通信。

          哨兵集群中各個(gè)實(shí)現(xiàn)通信后,就可以判定主庫(kù)是否已客觀下線(xiàn)。

          在已判定主庫(kù)已下線(xiàn)后,又如何選舉出新的主庫(kù)?

          新主庫(kù)選舉按照一定條件篩選出的符合條件的從庫(kù),并按照一定規(guī)則對(duì)其進(jìn)行打分,最高分者為新主庫(kù)。

          通常一定條件包括:

          • 從庫(kù)的當(dāng)前在線(xiàn)狀態(tài),
          • 判斷它之前的網(wǎng)絡(luò)連接狀態(tài),通過(guò)down-after-milliseconds * num(斷開(kāi)連接次數(shù)),當(dāng)斷開(kāi)連接次數(shù)超過(guò)閾值,不適合為新主庫(kù)。

          一定規(guī)則包括

          • 從庫(kù)優(yōu)先級(jí) , 通過(guò)slave-priority?配置項(xiàng),給不同的從庫(kù)設(shè)置不同優(yōu)先級(jí),優(yōu)先級(jí)最高的從庫(kù)得分高
          • 從庫(kù)復(fù)制進(jìn)度,和舊主庫(kù)同步程度最接近的從庫(kù)得分高,通過(guò)repl_backlog_buffer緩沖區(qū)記錄主庫(kù)?master_repl_offset?和從庫(kù)slave_repl_offset?相差最小高分
          • 從庫(kù) ID 號(hào) , ID 號(hào)小的從庫(kù)得分高。

          全都都基于在只有在一定規(guī)則中的某一輪評(píng)出最高分從庫(kù)就選舉結(jié)束,哨兵發(fā)起主從切換。

          leader哨兵


          選舉完新的主庫(kù)后,不能每個(gè)哨兵都發(fā)起主從切換,需要選舉成leader哨兵,那如何選舉leader哨兵執(zhí)行主從切換?

          選舉leader哨兵,也是基于少數(shù)服從多數(shù)原則"投票仲裁"選舉出來(lái),

          • 當(dāng)任何一個(gè)從庫(kù)判定主庫(kù)“主觀下線(xiàn)”后,發(fā)送命令?s-master-down-by-addr命令發(fā)送想要成為L(zhǎng)eader的信號(hào),
          • 其他哨兵根據(jù)與主機(jī)連接情況作出相對(duì)的響應(yīng),贊成票Y,反對(duì)票N,而且如果有多個(gè)哨兵發(fā)起請(qǐng)求,每個(gè)哨兵的贊成票只能投給其中一個(gè),其他只能為反對(duì)票。

          想要成為L(zhǎng)eader 的哨兵,要滿(mǎn)足兩個(gè)條件:

          • 第一,獲得半數(shù)以上的贊成票;
          • 第二,獲得的票數(shù)同時(shí)還需要大于等于哨兵配置文件中的quorum值。

          選舉完leader哨兵并新主庫(kù)切換完畢之后,那么leader哨兵怎么通知客戶(hù)端?

          還是基于哨兵自身的 pub/sub 功能,實(shí)現(xiàn)了客戶(hù)端和哨兵之間的事件通知,客戶(hù)端訂閱哨兵自身消息頻道 ,而且哨兵提供的消息訂閱頻道有很多,不同頻道包含了:

          事件相關(guān)頻道
          主庫(kù)下線(xiàn)事件+sdown(實(shí)例進(jìn)入“主觀下線(xiàn)”狀態(tài))
          -sdown(實(shí)例退出“主觀下線(xiàn)”狀態(tài))
          +odown(實(shí)例進(jìn)入“客觀下線(xiàn)”狀態(tài))
          -odown(實(shí)例退出“客觀下線(xiàn)”狀態(tài))
          新主庫(kù)切換+ switch-master(主庫(kù)地址發(fā)生變化)


          其中,當(dāng)客戶(hù)端從哨兵訂閱消息主從庫(kù)切換,當(dāng)主庫(kù)切換后,端戶(hù)端就會(huì)接收到新主庫(kù)的連接信息:

          switch-master?????

          在這樣的方式哨兵就可以通知客戶(hù)端切換了新庫(kù)。

          基于上述的機(jī)制和原理Redis實(shí)現(xiàn)了高可用,但也會(huì)帶了一些潛在的風(fēng)險(xiǎn),比如數(shù)據(jù)缺失。



          數(shù)據(jù)問(wèn)題


          Redis實(shí)現(xiàn)高可用,但實(shí)現(xiàn)期間可能產(chǎn)出一些風(fēng)險(xiǎn):

          • 主備切換的過(guò)程, 異步復(fù)制導(dǎo)致的數(shù)據(jù)丟失
          • 腦裂導(dǎo)致的數(shù)據(jù)丟失
          • 主備切換的過(guò)程,異步復(fù)制導(dǎo)致數(shù)據(jù)不一致


          數(shù)據(jù)丟失-主從異步復(fù)制


          因?yàn)閙aster 將數(shù)據(jù)復(fù)制給slave是異步實(shí)現(xiàn)的,在復(fù)制過(guò)程中,這可能存在master有部分?jǐn)?shù)據(jù)還沒(méi)復(fù)制到slave,master就宕機(jī)了,此時(shí)這些部分?jǐn)?shù)據(jù)就丟失了。

          總結(jié):主庫(kù)的數(shù)據(jù)還沒(méi)有同步到從庫(kù),結(jié)果主庫(kù)發(fā)生了故障,未同步的數(shù)據(jù)就丟失了。

          數(shù)據(jù)丟失-腦裂


          何為腦裂?當(dāng)一個(gè)集群中的 master 恰好網(wǎng)絡(luò)故障,導(dǎo)致與 sentinal 通信不上了,sentinal會(huì)認(rèn)為master下線(xiàn),且sentinal選舉出一個(gè)slave 作為新的 master,此時(shí)就存在兩個(gè) master了。

          此時(shí),可能存在client還沒(méi)來(lái)得及切換到新的master,還繼續(xù)寫(xiě)向舊master的數(shù)據(jù),當(dāng)master再次恢復(fù)的時(shí)候,會(huì)被作為一個(gè)slave掛到新的master 上去,自己的數(shù)據(jù)將會(huì)清空,重新從新的master 復(fù)制數(shù)據(jù),這樣就會(huì)導(dǎo)致數(shù)據(jù)缺失。

          總結(jié):主庫(kù)的數(shù)據(jù)還沒(méi)有同步到從庫(kù),結(jié)果主庫(kù)發(fā)生了故障,等從庫(kù)升級(jí)為主庫(kù)后,未同步的數(shù)據(jù)就丟失了。

          數(shù)據(jù)丟失解決方案


          數(shù)據(jù)丟失可以通過(guò)合理地配置參數(shù) min-slaves-to-write 和 min-slaves-max-lag 解決,比如

          • min-slaves-to-write?1
          • min-slaves-max-lag?10

          如上兩個(gè)配置:要求至少有 1 個(gè) slave,數(shù)據(jù)復(fù)制和同步的延遲不能超過(guò) 10 秒,如果超過(guò) 1 個(gè) slave,數(shù)據(jù)復(fù)制和同步的延遲都超過(guò)了 10 秒鐘,那么這個(gè)時(shí)候,master 就不會(huì)再接收任何請(qǐng)求了。

          數(shù)據(jù)不一致


          在主從異步復(fù)制過(guò)程,當(dāng)從庫(kù)因?yàn)榫W(wǎng)絡(luò)延遲或執(zhí)行復(fù)雜度高命令阻塞導(dǎo)致滯后執(zhí)行同步命令,這樣就會(huì)導(dǎo)致數(shù)據(jù)不一致

          解決方案:可以開(kāi)發(fā)一個(gè)外部程序來(lái)監(jiān)控主從庫(kù)間的復(fù)制進(jìn)度(master_repl_offset 和 slave_repl_offset ),通過(guò)監(jiān)控 master_repl_offset 與slave_repl_offset差值得知復(fù)制進(jìn)度,當(dāng)復(fù)制進(jìn)度不符合預(yù)期設(shè)置的Client不再?gòu)脑搹膸?kù)讀取數(shù)據(jù)。





          總結(jié)


          Redis使用主從復(fù)制、持久化、哨兵機(jī)制等實(shí)現(xiàn)高可用,需要理解其實(shí)現(xiàn)過(guò)程,也要明白其帶了風(fēng)險(xiǎn)以及解決方案,才能在實(shí)際項(xiàng)目更好優(yōu)化,提升系統(tǒng)的可靠性、穩(wěn)定性。



          點(diǎn)擊左下角閱讀原文,到?SegmentFault 思否社區(qū)?和文章作者展開(kāi)更多互動(dòng)和交流,或掃描下方二維碼添加“?SF 思否小姐姐?”,回復(fù)“?入群?”即可加入我們的技術(shù)交流群,收獲更多的技術(shù)文章~

          -?END -

          瀏覽 20
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  免费在线观看一区 | 成人无码小说 | 99久久婷婷国产精品2020 | 学生妹A毛片 | 综合激情网站 |