天天看點

高可用的技巧

文章目錄

  • ​​1.系統拆分​​
  • ​​2.解耦​​
  • ​​3.異步​​
  • ​​4.重試​​
  • ​​5.補償​​
  • ​​6.備份​​
  • ​​7.多活政策​​
  • ​​8.隔離​​
  • ​​9.限流​​
  • ​​10.熔斷​​
  • ​​11.降級​​

1.系統拆分

微服務架構,将一個複雜的業務域按DDD的思想拆分成若幹子系統,每個子系統負責專屬的業務功能,做好垂直化建設,各個子系統之間做好邊界隔離,降低風險蔓延。

2.解耦

高内聚、低耦合。小到接口抽象、MVC 分層,大到 SOLID 原則、23種設計模式。核心都是降低不同子產品間的耦合度,避免一處錯誤改動影響到整個系統。

就以開閉原則為例,對擴充是開放的,對修改是關閉的。随着業務功能疊代,如何做到每次改動不對原來的舊代碼産生影響。

Spring 架構給我們提供了一個很好的思路,裡面有個重要設計 ​

​AOP​

​ ,全稱(Aspect Oriented Programming),面向切面程式設計。

核心就是采用動态代理技術,通過對位元組碼進行增強,在方法調用的時候進行攔截,以便于在方法調用前後,增加我們需要的額外處理邏輯。

當然還有一個重要思路就是​

​事件機制​

​,通過釋出訂閱模式,新增的需求,隻需要訂閱對應的事件通知,針對性消費即可。不會對原來的代碼侵入性修改,是不是會好很多。

3.異步

如果是非實時響應的動作可以采用異步來完成,線程不需要一直等待,而是繼續執行後面的邏輯。

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

高可用的技巧

比如一個使用者在淘寶下了一筆購物訂單,關心的是訂單是否建立成功,能否進行後續的付款流程

至于其他業務動作,如短信通知、郵件通知、生成訂單快照、建立逾時任務記錄,這些非核心動作使用者并不是特别關心。

我們可以采用消息隊列的釋出/訂閱 機制,資料庫插入訂單記錄後,釋出一條消息到 MQ,然後就可以告知使用者下單成功。

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

4.重試

重試主要是展現在遠端的RPC調用,受 網絡抖動、線程資源阻塞 等因素影響,請求無法及時響應。

為了提升使用者體驗,調用方可以通過 重試 方式再次發送請求,嘗試擷取結果。比過:浏覽器的 F5 重新整理機制就是類似道理。

接口重試是一把雙刃劍,雖然用戶端收到了響應逾時結果,但是我們無法确定,服務端是否已經執行完成。如果盲目地重試,可能會帶來嚴重後果。比如:銀行轉賬。

重試通常跟幂等組合使用,如果一個接口支援了 幂等,那你就可以随便重試

關于的 幂等 的解決方案

  • 插入前先執行查詢操作,看是否存在,再決定是否插入
  • 增加唯一索引
  • 建防重表
  • 引入狀态機,比如付款後,訂單狀态調整為已付款,SQL 更新記錄前 增加條件判斷
  • 增加分布式鎖
  • 采用 Token 機制,服務端增加 token 校驗,隻有第一次請求是合法的

5.補償

我們知道不是所有的請求都能收到成功響應。除了上面的 重試 機制外,我們還可以采用補償玩法,實作資料最終一緻性。

業務補償根據處理的方向分為兩部分:

  1. 正向。多個操作構成一個分布式事務,如果部分成功、部分失敗,我們會通過最大努力機制将失敗的任務推進到成功狀态
  2. 逆向。同上道理,我們也可以采用反向操作,将部分成功任務恢複到初始狀态

補償操作有個重要前提,業務能接受短時間内的資料不一緻。

實作方式:

  1. 本地建表方式,存儲相關資料,然後通過定時任務掃描提取,并借助反射機制觸發執行
  2. 也可以采用簡單的消息中間件,建構業務消息體,由下遊的的消費任務執行。如果失敗,可以借助MQ的重試機制,多次重試

6.備份

任何伺服器都有當機的可能性,一旦存儲了資料,帶上狀态,如果發生故障,資料丢失,後果是我們無法承受的。

是以,容災備份也就變成了網際網路的基本能力。

高可用的技巧

Redis 借助 RDB 和 AOF 來實作兩台伺服器間的資料同步

  • RDB,全量資料同步
  • AOF,增量資料同步,回放日志

為了預防主節點挂了的情況。這裡引入哨兵機制。哨兵機制可以實作主從庫的自動切換,有效解決了故障轉移。整個過程分為三個階段:監控、選主、通知。

除了 Redis 中間件外,其他常見的​

​MySQL​

​​、​

​Kafka​

​​ 消息中間件、​

​HBase​

​​ 、​

​ES​

​​ 等 ,凡是涉及到​

​資料存儲的媒體​

​​,都有​

​備份機制​

​​,一旦主節點挂了,會啟用備份節點,保證​

​資料不會丢失​

​。

7.多活政策

有了備份不一定可以達到高可用

在一些極端情況,如:機房斷電、機房火災、地震、山洪等不可抗力因素,所有的伺服器都可能出現故障,無法對外提供服務,導緻整體業務癱瘓。

為了降低風險,保證服務的24小時可用性,我們會采用 ​

​多活政策​

​。

常見的多活方案有,​

​同城雙活​

​​、​

​兩地三中心​

​​、​

​三地五中心​

​​、​

​異地雙活​

​​、​

​異地多活​

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

8.隔離

隔離屬于​

​實體層面​

​的分割,将若幹的系統低耦合設計,獨立部署,從實體上隔開。

每個子系統有自己獨立的代碼庫,獨立開發,獨立釋出。一旦出現故障,也不會互相幹擾。當然如果不同子系統間有互相依賴,這種情況比較特殊,需要有預設值或者異常特殊處理,這屬于​

​業務層面​

​解決方案。

隔離屬于分布式技術的衍生産物,我們最常見的​

​微服務​

​解決方案。

将一個大型的複雜系統拆分成若幹個微服務系統,這些微服務子系統通常由不同的團隊開發、維護,獨立部署,服務之間通過 ​

​RPC​

​ 遠端調用。

​隔離​

​​使得系統間邊界更加​

​清晰​

​​,故障可以更加隔離開來,問題的發現與解決也更加快速,​

​系統的可用性也更高​

​。

9.限流

高并發系統,如果遇到流量洪峰,超過了目前系統的承載能力。我們要怎麼辦?

一種方案,照單全收,CPU、記憶體、Load負載飚的很高,最後處理不過來,所有請求都逾時無法正常響應。

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

限流分為單機版限流、分布式限流

10.熔斷

熔斷,其實是對調用鍊路中某個資源出現不穩定狀态時(如:調用逾時或異常比例升高),對這個資源的調用進行限制,讓請求快速失敗,避免影響到其它的資源而導緻級聯錯誤。

熔斷的主要方式是使用斷路器阻斷對故障伺服器的調用

斷路器有三種狀态,關閉、打開、半打開。

狀态機:

高可用的技巧
  • 關閉(Closed)狀态:在這個狀态下,請求都會被轉發給後端服務。同時會記錄請求失敗的次數,當請求失敗次數在一段時間超過一定次數就會進入打開狀态。
  • 打開(Open)狀态:在這個狀态下,熔斷器會直接拒絕請求,傳回錯誤,而不去調用後端服務。同時,會有一個定時器,時間到的時候會變成半打開狀态。目的是假設服務會在一段時間内恢複正常。
  • 半打開(Half Open)狀态:在這個狀态下,熔斷器會嘗試把部分請求轉發給後端服務,目的是為了探測後端服務是否恢複。如果請求失敗會進入打開狀态,成功情況下會進入關閉狀态,同時重置計數。

11.降級

降級是系統保護的一種重要手段。

正如 “好鋼用在刀刃上”,為了使有限資源發揮最大價值,我們會臨時關閉一些非核心功能,減輕系統壓力,并将有限資源留給核心業務。