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

          聊聊高可用的 11 個關(guān)鍵技巧

          共 4040字,需瀏覽 9分鐘

           ·

          2022-04-20 19:38


          源?/微觀技術(shù)?? ? ? ??文/?


          大型互聯(lián)網(wǎng)架構(gòu)設(shè)計,講究一個四件套組合拳玩法,高并發(fā)高性能高可用高擴(kuò)展

          如果能掌握這四個方面,應(yīng)付大廠面試以及日常工作中的架構(gòu)方案設(shè)計基本不是什么難題。

          今天,Tom哥就帶大家學(xué)習(xí)下高可用都有哪些設(shè)計技巧?


          一、系統(tǒng)拆分

          有句古話 "牽一發(fā)而動全身"。

          面對一個龐然大物,如果沒有一個合理的分工分層。任何一個小小失誤都會被無限放大,釀成巨大災(zāi)難。

          萬物相通,回到我們的軟件架構(gòu)。

          早前的系統(tǒng)都是單體系統(tǒng),比如電商業(yè)務(wù),會員、商品、訂單、物流、營銷等模塊都堆積在一個系統(tǒng)。每到節(jié)假日搞個大促活動,系統(tǒng)擴(kuò)容時,一擴(kuò)全擴(kuò),一掛全掛。只要一個接口出了問題,整個系統(tǒng)都不可用。

          “雞蛋不能放在一個籃子里”,這種連帶風(fēng)險換誰都承受不起。

          因此,系統(tǒng)拆分?成了更多人的選擇。

          慢慢的就有了我們現(xiàn)在看到的微服務(wù)架構(gòu),將一個復(fù)雜的業(yè)務(wù)域按DDD的思想拆分成若干子系統(tǒng),每個子系統(tǒng)負(fù)責(zé)專屬的業(yè)務(wù)功能,做好垂直化建設(shè),各個子系統(tǒng)之間做好邊界隔離,降低風(fēng)險蔓延。

          二、解耦

          軟件開發(fā)有個重要原則“高內(nèi)聚、低耦合”。

          小到接口抽象MVC 分層,大到?SOLID 原則23種設(shè)計模式。核心都是降低不同模塊間的耦合度,避免一處錯誤改動影響到整個系統(tǒng)。

          就以開閉原則為例,對擴(kuò)展是開放的,對修改是關(guān)閉的。隨著業(yè)務(wù)功能迭代,如何做到每次改動不對原來的舊代碼產(chǎn)生影響。

          Spring 框架給我們提供了一個很好的思路,里面有個重要設(shè)計?AOP?,全稱(Aspect Oriented Programming),面向切面編程。

          核心就是采用動態(tài)代理技術(shù),通過對字節(jié)碼進(jìn)行增強,在方法調(diào)用的時候進(jìn)行攔截,以便于在方法調(diào)用前后,增加我們需要的額外處理邏輯。

          當(dāng)然還有一個重要思路就是事件機(jī)制,通過發(fā)布訂閱模式,新增的需求,只需要訂閱對應(yīng)的事件通知,針對性消費即可。不會對原來的代碼侵入性修改,是不是會好很多。

          三、異步

          同步指一個進(jìn)程在執(zhí)行請求的時候,若該請求需要一段時間才能返回信息,那么這個進(jìn)程將會一直等待下去,直到收到返回信息才繼續(xù)執(zhí)行下去。

          效率會大大降低,聰明的人想到了?異步?方式。

          如果是非實時響應(yīng)的動作可以采用異步來完成,線程不需要一直等待,而是繼續(xù)執(zhí)行后面的邏輯。

          如:線程池(ThreadPoolExecutor)、消息隊列 等都是這個原理

          比如一個用戶在淘寶下了一筆購物訂單,關(guān)心的是訂單是否創(chuàng)建成功,能否進(jìn)行后續(xù)的付款流程

          至于其他業(yè)務(wù)動作,如短信通知、郵件通知、生成訂單快照、創(chuàng)建超時任務(wù)記錄,這些非核心動作用戶并不是特別關(guān)心。

          我們可以采用消息隊列的發(fā)布/訂閱?機(jī)制,數(shù)據(jù)庫插入訂單記錄后,發(fā)布一條消息到 MQ,然后就可以告知用戶下單成功。

          其他事情,由不同的 Task 任務(wù)訂閱消息異步處理,彼此間互不干擾。

          四、重試

          重試主要是體現(xiàn)在遠(yuǎn)程的RPC調(diào)用,受?網(wǎng)絡(luò)抖動線程資源阻塞?等因素影響,請求無法及時響應(yīng)。

          為了提升用戶體驗,調(diào)用方可以通過?重試?方式再次發(fā)送請求,嘗試獲取結(jié)果。比過:瀏覽器的 F5 刷新機(jī)制就是類似道理。

          接口重試是一把雙刃劍,雖然客戶端收到了響應(yīng)超時結(jié)果,但是我們無法確定,服務(wù)端是否已經(jīng)執(zhí)行完成。如果盲目地重試,可能會帶來嚴(yán)重后果。比如:銀行轉(zhuǎn)賬。

          重試通常跟冪等組合使用,如果一個接口支持了?冪等,那你就可以隨便重試

          關(guān)于的?冪等?的解決方案

          • 插入前先執(zhí)行查詢操作,看是否存在,再決定是否插入
          • 增加唯一索引
          • 建防重表
          • 引入狀態(tài)機(jī),比如付款后,訂單狀態(tài)調(diào)整為已付款,SQL 更新記錄前 增加條件判斷
          • 增加分布式鎖
          • 采用 Token 機(jī)制,服務(wù)端增加 token 校驗,只有第一次請求是合法的

          五、補償

          我們知道不是所有的請求都能收到成功響應(yīng)。除了上面的?重試?機(jī)制外,我們還可以采用補償玩法,實現(xiàn)數(shù)據(jù)最終一致性

          業(yè)務(wù)補償根據(jù)處理的方向分為兩部分:

          • 正向。多個操作構(gòu)成一個分布式事務(wù),如果部分成功、部分失敗,我們會通過最大努力機(jī)制將失敗的任務(wù)推進(jìn)到成功狀態(tài)
          • 逆向。同上道理,我們也可以采用反向操作,將部分成功任務(wù)恢復(fù)到初始狀態(tài)

          注意:補償操作有個重要前提,業(yè)務(wù)能接受短時間內(nèi)的數(shù)據(jù)不一致。

          補償有很多的實現(xiàn)方式:

          1、本地建表方式,存儲相關(guān)數(shù)據(jù),然后通過定時任務(wù)掃描提取,并借助反射機(jī)制觸發(fā)執(zhí)行

          2、也可以采用簡單的消息中間件,構(gòu)建業(yè)務(wù)消息體,由下游的的消費任務(wù)執(zhí)行。如果失敗,可以借助MQ的重試機(jī)制,多次重試

          六、備份

          任何服務(wù)器都有宕機(jī)的可能性,一旦存儲了數(shù)據(jù),帶上狀態(tài),如果發(fā)生故障,數(shù)據(jù)丟失,后果是我們無法承受的。

          所以,容災(zāi)備份也就變成了互聯(lián)網(wǎng)的基本能力。

          那如何備份,不同的框架有不用的玩法。我們以 Redis 為例:

          Redis 借助?RDB?和?AOF?來實現(xiàn)兩臺服務(wù)器間的數(shù)據(jù)同步

          • RDB,全量數(shù)據(jù)同步
          • AOF,增量數(shù)據(jù)同步,回放日志

          一旦主節(jié)點掛了怎么辦?

          這里引入哨兵機(jī)制。哨兵機(jī)制可以實現(xiàn)主從庫的自動切換,有效解決了故障轉(zhuǎn)移。整個過程分為三個階段:監(jiān)控、選主、通知。

          除了 Redis 中間件外,其他常見的 MySQL、Kafka 消息中間件、HBase 、ES 等 ,凡是涉及到數(shù)據(jù)存儲的介質(zhì),都有備份機(jī)制,一旦主節(jié)點掛了,會啟用備份節(jié)點,保證數(shù)據(jù)不會丟失。

          七、多活策略

          雖然有了上面的備份策略,那是不是就萬事大吉呢?

          在一些極端情況,如:機(jī)房斷電、機(jī)房火災(zāi)、地震、山洪等不可抗力因素,所有的服務(wù)器都可能出現(xiàn)故障,無法對外提供服務(wù),導(dǎo)致整體業(yè)務(wù)癱瘓。

          為了降低風(fēng)險,保證服務(wù)的24小時可用性,我們會采用?多活策略

          常見的多活方案有,同城雙活兩地三中心三地五中心異地雙活異地多活

          不同的方案技術(shù)要求、建設(shè)成本、運維成本也都不一樣。

          多活的技術(shù)方案復(fù)雜,需要考慮的問題點也非常多,這里只是拋磚引玉就不過多展開

          八、隔離

          隔離屬于物理層面的分割,將若干的系統(tǒng)低耦合設(shè)計,獨立部署,從物理上隔開。

          每個子系統(tǒng)有自己獨立的代碼庫,獨立開發(fā),獨立發(fā)布。一旦出現(xiàn)故障,也不會相互干擾。當(dāng)然如果不同子系統(tǒng)間有相互依賴,這種情況比較特殊,需要有默認(rèn)值或者異常特殊處理,這屬于業(yè)務(wù)層面解決方案。

          隔離屬于分布式技術(shù)的衍生產(chǎn)物,我們最常見的微服務(wù)解決方案。

          將一個大型的復(fù)雜系統(tǒng)拆分成若干個微服務(wù)系統(tǒng),這些微服務(wù)子系統(tǒng)通常由不同的團(tuán)隊開發(fā)、維護(hù),獨立部署,服務(wù)之間通過?RPC?遠(yuǎn)程調(diào)用。

          隔離使得系統(tǒng)間邊界更加清晰,故障可以更加隔離開來,問題的發(fā)現(xiàn)與解決也更加快速,系統(tǒng)的可用性也更高。

          九、限流

          高并發(fā)系統(tǒng),如果遇到流量洪峰,超過了當(dāng)前系統(tǒng)的承載能力。我們要怎么辦?

          一種方案,照單全收,CPU、內(nèi)存、Load負(fù)載飚的很高,最后處理不過來,所有請求都超時無法正常響應(yīng)。

          另一種解決方案,“舍得,有舍有得”,多余的流量我們直接丟棄。

          限流定義:

          限制到達(dá)系統(tǒng)的并發(fā)請求數(shù)量,保證系統(tǒng)能夠正常響應(yīng)部分用戶請求,而對于超過限制的流量,則通過拒絕服務(wù)的方式保證整體系統(tǒng)的可用性。

          根據(jù)作用范圍:限流分為單機(jī)版限流、分布式限流

          1、單機(jī)版限流

          主要借助于本機(jī)內(nèi)存來實現(xiàn)計數(shù)器,比如通過AtomicLong#incrementAndGet(),但是要注意之前不用的key定期做清理,釋放內(nèi)存。

          純內(nèi)存實現(xiàn),無需和其他節(jié)點統(tǒng)計匯總,性能最高。但是優(yōu)點也是缺點,無法做到全局統(tǒng)一化的限流。

          2、分布式限流

          單機(jī)版限流僅能保護(hù)自身節(jié)點,但無法保護(hù)應(yīng)用依賴的各種服務(wù),并且在進(jìn)行節(jié)點擴(kuò)容、縮容時也無法準(zhǔn)確控制整個服務(wù)的請求限制。而分布式限流,以集群為維度,可以方便的控制這個集群的請求限制,從而保護(hù)下游依賴的各種服務(wù)資源。

          限流支持多個維度:

          • 整個系統(tǒng)一定時間內(nèi)(比如每分鐘)處理多少請求
          • 單個接口一定時間內(nèi)處理多少流量
          • 單個IP、城市、渠道、設(shè)備id、用戶id等在一定時間內(nèi)發(fā)送的請求數(shù)
          • 如果是開放平臺,則為每個appkey設(shè)置獨立的訪問速率規(guī)則

          常見的限流算法:

          • 計數(shù)器限流
          • 滑動窗口限流
          • 漏桶限流
          • 令牌桶限流

          十、熔斷

          熔斷,其實是對調(diào)用鏈路中某個資源出現(xiàn)不穩(wěn)定狀態(tài)時(如:調(diào)用超時或異常比例升高),對這個資源的調(diào)用進(jìn)行限制,讓請求快速失敗,避免影響到其它的資源而導(dǎo)致級聯(lián)錯誤。

          熔斷的主要方式是使用斷路器阻斷對故障服務(wù)器的調(diào)用

          斷路器有三種狀態(tài),關(guān)閉、打開、半打開。

          狀態(tài)機(jī):

          1、關(guān)閉(Closed)狀態(tài):在這個狀態(tài)下,請求都會被轉(zhuǎn)發(fā)給后端服務(wù)。同時會記錄請求失敗的次數(shù),當(dāng)請求失敗次數(shù)在一段時間超過一定次數(shù)就會進(jìn)入打開狀態(tài)。

          2、打開(Open)狀態(tài):在這個狀態(tài)下,熔斷器會直接拒絕請求,返回錯誤,而不去調(diào)用后端服務(wù)。同時,會有一個定時器,時間到的時候會變成半打開狀態(tài)。目的是假設(shè)服務(wù)會在一段時間內(nèi)恢復(fù)正常。

          3、半打開(Half Open)狀態(tài):在這個狀態(tài)下,熔斷器會嘗試把部分請求轉(zhuǎn)發(fā)給后端服務(wù),目的是為了探測后端服務(wù)是否恢復(fù)。如果請求失敗會進(jìn)入打開狀態(tài),成功情況下會進(jìn)入關(guān)閉狀態(tài),同時重置計數(shù)。

          目前,市面流行的解決方案是阿里的開源框架?Sentinel,提供了Dashboard控制臺用于定義資源以及規(guī)則配置

          十一、降級

          降級是系統(tǒng)保護(hù)的一種重要手段。

          正如 “好鋼用在刀刃上”,為了使有限資源發(fā)揮最大價值,我們會臨時關(guān)閉一些非核心功能,減輕系統(tǒng)壓力,并將有限資源留給核心業(yè)務(wù)。

          比如電商大促,業(yè)務(wù)在峰值時刻,系統(tǒng)抵擋不住全部的流量時,系統(tǒng)的負(fù)載、CPU 的使用率都超過了預(yù)警水位,可以對一些非核心的功能進(jìn)行降級,降低系統(tǒng)壓力,比如把商品評價成交記錄等功能臨時關(guān)掉。棄車保帥,保證?創(chuàng)建訂單訂單支付?等核心功能的正常使用。

          當(dāng)然,不同業(yè)務(wù)、不同公司,處理方式也各不相同,需要結(jié)合實際場景,和業(yè)務(wù)方同學(xué)一塊討論,最后達(dá)成一個統(tǒng)一認(rèn)可的降級方案。

          總結(jié)下來:降級是通過暫時關(guān)閉某些非核心服務(wù)或者組件從而保護(hù)核心系統(tǒng)的可用性。

          end





          頂級程序員:topcoding

          做最好的程序員社區(qū):Java后端開發(fā)、Python、大數(shù)據(jù)、AI


          一鍵三連「分享」、「點贊」和「在看」



          瀏覽 5
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <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>
                  国产插逼区 | 可以免费观看的毛片 | 久久久久久久久久久国产 | 台湾娱乐成人网综合网 | 美女网站操逼视频国产 |