<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>

          大廠架構(gòu)都開(kāi)始做機(jī)房多活了

          共 3306字,需瀏覽 7分鐘

           ·

          2021-07-31 08:25

          寫(xiě)在前面


          B站掛了的那天,就想寫(xiě)寫(xiě)機(jī)房多活的文章,但考慮到這方面的技術(shù)面涉及比較廣,一時(shí)無(wú)從下手就拖到了現(xiàn)在,未來(lái)會(huì)陸續(xù)基于“多活”這個(gè)話題聊一聊我的經(jīng)驗(yàn)。


          在互聯(lián)網(wǎng)行業(yè),一定規(guī)模的業(yè)務(wù)做“異地多活”都是標(biāo)配了,做好“多活”價(jià)值很大,當(dāng)然做好“多活”設(shè)計(jì)也很難,涉及到網(wǎng)絡(luò)、數(shù)據(jù)、事務(wù)、冗余等各種挑戰(zhàn)。需要解決多活帶來(lái)的技術(shù)問(wèn)題,比如“怎么保證跨機(jī)房數(shù)據(jù)的一致性”、“如何保證異地事務(wù)一致性”、“怎么在多個(gè)異地之間無(wú)縫切換”。



          通用的多活架構(gòu)


          我們先看一個(gè)通用的多活架構(gòu)圖是什么樣的,如下圖所示:

          上圖可以看做是一個(gè)基于用戶分區(qū)的架構(gòu),每個(gè)用戶有自己所屬的分區(qū),在每個(gè)分區(qū)內(nèi)有用戶自己相關(guān)的主要數(shù)據(jù)。比如用戶A主數(shù)據(jù)分區(qū)是A,用戶B主數(shù)據(jù)分區(qū)是B。


          用戶可以就近接入離他最近的機(jī)房,Router層可以看做是一個(gè)Nginx or LVS的路由層,我們將路由規(guī)則下發(fā)到這層,基于用戶數(shù)據(jù)(手機(jī)號(hào)、uid等)做hash,路由到不同的數(shù)據(jù)分區(qū),應(yīng)用服務(wù)與數(shù)據(jù)自閉環(huán)在分區(qū)內(nèi)。


          為提高分區(qū)的容災(zāi)能力,每個(gè)分區(qū)冗余另外兩個(gè)分區(qū)的數(shù)據(jù),比如A分區(qū)里面除了有自己的分區(qū)數(shù)據(jù)外,還有B、C分區(qū)的數(shù)據(jù)。


          業(yè)務(wù)上的取舍


          多活本質(zhì)上也是可用性的一種保障機(jī)制,做好可用性,大家首先想到的就是冗余,而冗余是有成本的,成本包括資源成本和系統(tǒng)因?yàn)楦呖捎脧?fù)雜度提升的人力成本。


          所以多活首先要做的就是服務(wù)分級(jí),只有那些核心鏈路上的核心業(yè)務(wù)才有必要投入這些成本做多活。


          也就是說(shuō):不是所有業(yè)務(wù)都需要做異地多活,核心業(yè)務(wù)才需要。


          架構(gòu)本質(zhì)是取舍,我們看看如何基于核心業(yè)務(wù)場(chǎng)景做業(yè)務(wù)上的取舍。


          想象一個(gè)問(wèn)題,比如A用戶本來(lái)的數(shù)據(jù)分區(qū)是A,但如果A掛掉了,想讓A用戶到分區(qū)B繼續(xù)工作,由于數(shù)據(jù)同步是異步的,可能這時(shí)B里面并不是所有的A用戶數(shù)據(jù)都有。


          這個(gè)問(wèn)題是常態(tài),所以就需要考慮我們業(yè)務(wù)上是否可以低成本方式兼容類似的問(wèn)題了。


          以注冊(cè)為例,如果A用戶注冊(cè)數(shù)據(jù)沒(méi)有同步到B分區(qū),那在B分區(qū)A用戶就不能工作了嗎?肯定不是。


          在業(yè)務(wù)上讓用戶A在分區(qū)B重新注冊(cè)就好了,這部分?jǐn)?shù)據(jù)一致性與可靠性要求不高。通過(guò)這種方式,注冊(cè)功能就無(wú)形中實(shí)現(xiàn)了“多活”。


          所以讓那些真正核心業(yè)務(wù)做好多活即可,以B站為例,登錄、看視頻是核心業(yè)務(wù)場(chǎng)景,充會(huì)員、打賞火箭有可能都不是核心業(yè)務(wù),也不需要花費(fèi)成本做多活了。


          解決異地?cái)?shù)據(jù)不一致的關(guān)鍵方案


          上面的例子提到了,解決一些業(yè)務(wù)多活的方式可以是允許不同分區(qū)內(nèi)存在數(shù)據(jù)不一致的情況,那如果故障恢復(fù)之后,如何解決不同分區(qū)下數(shù)據(jù)一致性問(wèn)題呢?簡(jiǎn)單來(lái)說(shuō)就是應(yīng)該用哪份數(shù)據(jù)?


          有可能后修改的數(shù)據(jù)由于分區(qū)之間異地延遲,導(dǎo)致先生效,反之也同樣成立。


          大部分場(chǎng)景此類問(wèn)題解決起來(lái)并不復(fù)雜,可以看成以后修改的為準(zhǔn)即可。但這個(gè)先后的判斷,不能以時(shí)間看,因?yàn)椴煌瑱C(jī)器、不同機(jī)房的時(shí)間可能是不準(zhǔn)的,最好的方式是采用全局唯一自增id,類似于Snowflake方式,誰(shuí)大依賴誰(shuí)。


          但需要考慮好這個(gè)唯一id生成服務(wù)的異地多活,我覺(jué)得還好,可以把這個(gè)id生成服務(wù)部署為分區(qū)內(nèi)獨(dú)立的,id生成就不存在沖突了。


          解決數(shù)據(jù)不能實(shí)時(shí)同步的矛盾


          做多活,還存在一個(gè)誤區(qū):“數(shù)據(jù)需要百分之百實(shí)時(shí)同步”。


          這是不可能的,以北京到上海為例,網(wǎng)絡(luò)傳輸延遲20~30ms,再加上上層業(yè)務(wù)處理的話,可能延遲在秒級(jí),所以百分百實(shí)時(shí)同步數(shù)據(jù)是不可能的。


          如何平衡業(yè)務(wù)上要求數(shù)據(jù)快速同步,而物理上做不到數(shù)據(jù)快速同步這個(gè)矛盾呢?


          完全解決這個(gè)矛盾是不可能的,我們能做的就是降低這個(gè)矛盾:

          1. 盡量減小異地機(jī)房之間的距離,搭建專線; 

          2. 盡量減少數(shù)據(jù)同步數(shù)量;

          3. 保障最終一致性,不保證實(shí)時(shí)一致性;

          4. 業(yè)務(wù)層面容錯(cuò)處理;


          盡量減小異地機(jī)房之間的距離,搭建專線


          減小異地機(jī)房之間的距離,可以采用同城雙活的方式,就是在一個(gè)城市里面搭建多個(gè)多活機(jī)房,這樣這些機(jī)房可以邏輯上看成一個(gè)機(jī)房。


          這種方案的優(yōu)點(diǎn)是:提高了性能;缺點(diǎn)是:不能做到城市層面的容災(zāi)。


          盡量減少數(shù)據(jù)同步數(shù)量


          由于數(shù)據(jù)同步需要占用機(jī)房之間專線帶寬,所以盡量只同步需要的數(shù)據(jù),不需要的不同步。


          保障最終一致性,不保證實(shí)時(shí)一致性


          既然物理上我們難以實(shí)現(xiàn)實(shí)時(shí)性,所以必須接受最終一致性這個(gè)事實(shí)。反映在架構(gòu)上,就是我們需要面對(duì)最終一致性這個(gè)特點(diǎn)設(shè)計(jì)架構(gòu)方案。


          不同存儲(chǔ)場(chǎng)景需要考慮不同最終一致性的時(shí)間窗口,是30ms、30s還是3小時(shí),我們?cè)诩夹g(shù)層面需要根據(jù)不同的業(yè)務(wù)特點(diǎn)進(jìn)行差異化的技術(shù)實(shí)現(xiàn),以滿足業(yè)務(wù)需求。


          業(yè)務(wù)層面容錯(cuò)處理


          將流量切到不同分區(qū)下,可以視為出現(xiàn)了系統(tǒng)故障。一般我們做降級(jí)、切流操作過(guò)程中,業(yè)務(wù)可能是有損的。也就是哪怕我們做了多活可用,也不能讓業(yè)務(wù)實(shí)現(xiàn)百分百的可用性,很多時(shí)候我們只需要實(shí)現(xiàn)99.99%即可。


          所以業(yè)務(wù)上需要針對(duì)于這個(gè)損失窗口做一定的容錯(cuò)設(shè)計(jì),提高用戶體驗(yàn)。比如分區(qū)內(nèi)緩存兜底、用戶動(dòng)線跳轉(zhuǎn)等,降低對(duì)于實(shí)時(shí)同步數(shù)據(jù)的依賴。


          數(shù)據(jù)同步


          通過(guò)上面內(nèi)容可以看出來(lái),做多活最重要的是對(duì)于有狀態(tài)服務(wù)的處理,數(shù)據(jù)同步是實(shí)現(xiàn)多活方案的核心。


          常用的中間件本身都具備一定的數(shù)據(jù)同步方案,比如mysql的主備復(fù)制、redis的cluster功能、es的集群功能,但僅僅采用這些存儲(chǔ)中間件提供的復(fù)制功能是不能解決異地?cái)?shù)據(jù)復(fù)制的問(wèn)題的。


          比如mysql的主從復(fù)制,大部分場(chǎng)景是滿足的,但對(duì)于這種跨異地機(jī)房的數(shù)據(jù)同步場(chǎng)景來(lái)說(shuō),mysql單線程復(fù)制功能在網(wǎng)絡(luò)抖動(dòng)時(shí)經(jīng)常發(fā)生延遲問(wèn)題,短則十幾秒,長(zhǎng)則十幾分鐘。而且mysql主從復(fù)制出現(xiàn)問(wèn)題時(shí),盡管發(fā)現(xiàn)了,但是沒(méi)辦法快速通過(guò)擴(kuò)容方式解決,只能干等。


          Redis 3.0之前的主從同步方案存在一個(gè)問(wèn)題,當(dāng)從機(jī)宕機(jī)或者與主機(jī)斷開(kāi)重連時(shí),會(huì)觸發(fā)全量的主從復(fù)制,這時(shí)主機(jī)會(huì)生成大量?jī)?nèi)存快照,由于數(shù)據(jù)量大,同步恢復(fù)時(shí)間長(zhǎng),從機(jī)就不能對(duì)外提供服務(wù)了。


          所以光依靠存儲(chǔ)系統(tǒng)本身的同步復(fù)制功能,在一些場(chǎng)合是不滿足業(yè)務(wù)需求的。特別是異地機(jī)房這種場(chǎng)景,寬帶有限,長(zhǎng)距離傳輸,網(wǎng)絡(luò)抖動(dòng)常態(tài)的情況下,光依靠存儲(chǔ)系統(tǒng)的同步功能是不能實(shí)現(xiàn)多活的。


          為解決以上問(wèn)題,大部分場(chǎng)景還是需要基于MQ實(shí)現(xiàn)最終的異地?cái)?shù)據(jù)復(fù)制。一方面自研更適合我們的業(yè)務(wù)場(chǎng)景,同時(shí)MQ本身具備很好的擴(kuò)容能力,在同步數(shù)據(jù)有壓力的情況下,可以快速進(jìn)行擴(kuò)容解決復(fù)制延遲問(wèn)題。


          其他數(shù)據(jù)同步方式:

          • 消息隊(duì)列同步方式;

          • 二次路由方式:當(dāng)消息隊(duì)列同步延遲了,導(dǎo)致目標(biāo)分區(qū)沒(méi)有數(shù)據(jù),可以強(qiáng)制讀取原分區(qū)獲取數(shù)據(jù),當(dāng)然這種只是解決流量進(jìn)入錯(cuò)誤的分區(qū),而不是分區(qū)故障的路由;

          • 存儲(chǔ)系統(tǒng)主從復(fù)制方式:為提高一個(gè)分區(qū)內(nèi)多機(jī)房的可用性(一般是同城雙活這種),可以采用存儲(chǔ)系統(tǒng)的主從同步復(fù)制能力,比如mysql的主從;

          • 重新生成方式:還有一種方式,數(shù)據(jù)不需要做跨數(shù)據(jù)中心的數(shù)據(jù)同步,或者可以容忍數(shù)據(jù)同步的丟失或延遲,所以解法可以是數(shù)據(jù)重建。比如分區(qū)內(nèi)的緩存數(shù)據(jù),可以基于跨數(shù)據(jù)分區(qū)同步,也可以基于分區(qū)內(nèi)元數(shù)據(jù)重建即可;


          我們需要做到多活的百分百可用嗎?


          百分百可用不可用達(dá)到,沒(méi)有任何一個(gè)系統(tǒng)可以承諾自己百分百可用。但如果有的業(yè)務(wù)要求百分百可用怎么辦呢?


          按照CAP定理來(lái)說(shuō),這屬于CP系統(tǒng),對(duì)于一致性要求高,那么只能舍棄A(可用性)了。


          這種場(chǎng)景一般是銀行類業(yè)務(wù),比如小明辦理了招商銀行賬號(hào),想通過(guò)招行轉(zhuǎn)賬的話,需要確保招行數(shù)據(jù)中心是可用的。不然會(huì)出現(xiàn)數(shù)據(jù)不一致問(wèn)題,解決允許轉(zhuǎn)賬再處理數(shù)據(jù)問(wèn)題的成本遠(yuǎn)大于不讓轉(zhuǎn)賬的成本與風(fēng)險(xiǎn),不讓轉(zhuǎn)賬是最合理的選擇。


          其實(shí)我們使用銀行類APP轉(zhuǎn)賬時(shí),可以看到他有自己的一些處理方式,比如交易時(shí)間內(nèi)不允許操作,先鎖金額記錄流水再轉(zhuǎn)賬等??梢园l(fā)現(xiàn)為了提高系統(tǒng)對(duì)于金錢(qián)的一致性處理,業(yè)務(wù)上犧牲了體驗(yàn),但這種體驗(yàn)的缺失是可以接受的。


          如果想讓體驗(yàn)更好一點(diǎn)的話,可以做些降級(jí)層面的體驗(yàn)優(yōu)化,比如掛公告:研發(fā)小哥哥在緊急處理問(wèn)題哦,或做事后的優(yōu)惠券補(bǔ)償,這是我們經(jīng)常采用的一種方式,給用戶發(fā)券既可以提升體驗(yàn),又可以增加轉(zhuǎn)化率可能。

          瀏覽 50
          點(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>
                  免费a v在线 | 台湾成人在线视频 | 丁香五月婷婷情 | 狠狠人妻久久 | 亚洲精品久久久久 |