高可用 - 隔離原則

前言

當討論高可用時,那麼必然有與之對應的低可用甚至不可用,但無論是哪種可用描述,其中都暗含了一個大衆共識,即不存在永久穩定運行的系統程序。

事實上,幾十年前圖靈也論證過類似的問題,稱爲“停機問題”,具體的描述是:能否爲A計算機編程,使得程序才能在有限時間內推斷出計算機B是否會停止運行?圖靈使用了十分簡潔但嚴謹的反證法論證了停機問題,具體論證方式在這裏就不贅述了,最終的結論就是不存在這種程序,也就是說,很不幸,我們無法一種可計算的方式解決停機問題。

所以無論是經驗共識還是邏輯論證,我們不得不面對一個現實,即世界上不存在能夠時刻保持穩定的系統程序。

基於這個現實,有無數的天才和應用實踐試圖儘可能的降低機器不可用的概率。所以我想當下談論到高可用時,就是在不斷試錯的路上交流經驗,但幸運的是,在我們之前有無數天才和實踐經驗供我們學習參考。

一、高可用

高可用這一概念是伴隨着計算機系統的發展和需求的增長逐漸形成。隨着分佈式系統的發展和互聯網的普及,需求與技術也在不斷演進和增長,高可用性已經成爲現代軟件系統架構中不可或缺的重要組成部分。

對於高可用的定義有很多種描述,但都是圍繞一個主題,即抵禦不確定性Distributed systems中定義可用性系統處於正常運行狀態的時間比例,如果用戶無法訪問系統,則稱該系統不可用

如果高可用的問題治理以時間維度劃分,可以大致分爲一下4個階段:分爲:事前(故障發生以前)、事發(故障發生到系統或人感知到故障)、事中(故障發生到故障處理這段時間)、事後(故障結束之後)。按照上述分類,不同的階段可以對應不同的技巧

1. 事前:副本、隔離、配額、提前預案、探知
2. 事發:監控、報警
3. 事中:降級、回滾、應急預案,failXXX系列
4. 事後:覆盤、思考、技改

相比於其他高可用原則而言,隔離原則是十分通用且易懂的,作爲保障高可用系統的基石,因爲隔離原則最大的作用就是應對爲系統提高抵禦各種“黑天鵝事件”的保障原則。



二、隔離原則(Isolation Principle)

2.1、定義

隔離原則作爲一個抽象的指導原則,並不屬於某一個具體的研究方向或領域,而是一個跨領域的設計概念。"隔離"字面意義已經描述的很充分,猶如艙壁隔離(Bulkhead Isolation)。

如果要形象的比喻隔離原則在保證系統高可用中的作用,我想可以描述爲一艘航行在大海上的巨輪與底層船艙的關係,當風平浪靜時,巨輪安穩前行;一旦遭遇海底暗礁、碰撞等嚴重災害是,船艙之間的隔離與堅固程度就是巨輪穩定前行的生命保證。





 

具體來說,隔離原則在系統設計中採取一系列方法,將系統組件、服務、資源和數據等隔離,儘可能減少相互影響,從而使得系統在對抗各種不確定性時,可以更好的將系統風險分散,提高系統整體可用性。

2.2、實現

雖然隔離原則十分易懂和重要,但它只是一種抽象的原則或設計方式,並不是一種嚴格的理論框架,實踐過程中,我們很難通過量化的方式說系統已經完全做到了充分隔離。

作爲系統設計的一部分,在微服務架構(Microservices Architecture)、數據庫系統(Database Systems)、網絡安全與隔離(Network Security and Isolation)、服務網格(Service Mesh)、應用程序隔離(Application Isolation)、環境隔離(Environment Isolation)、虛擬化技術(Virtualization Technology)等領域都可以稱爲隔離原則的具體實現。

上述描述有些過於抽象,以日常開發所能接觸到的實際應用爲例,如服務拆分、color網關、jsf對應着微服務架構領域;事務隔離、數據庫分區是數據庫系統的具體體現;jdos、編排部署則是容器技術實現;租戶隔離、垂直機房是環境隔離方向應用。

仔細分析下來,隔離原則指導下的技術產物在日常開發中無處不在,甚至於讓我們有了一種技術本身就該如此的錯覺,使用了最新的技術似乎就能保證系統的高可用。但現實經驗告訴我們,維持系統的高可用沒有這麼簡單。

事實上,我們可以帶着隔離原則重新審視一下日常的開發過程,重新感受隔離原則在現有技術架構下有哪些體現。



2.3 經驗與原則

對於一個抽象的原則而言,在工程實踐中往往會被總結爲一系列的規則建議。隔離原則在實際的開發設計中,隔離原則通常存在以下的實現方式和建議,我們可以從簡單的併發編程開始,感受隔離原則的具象化體現。

線程隔離

日常開發中,我們總會遇到機器數量受限場景,通常的做法就是併發編程,簡單的通過幾個線程交互完成對某項工作的處理。但當工作比較複雜時,我們一般會選擇自定義線程池,或者自己造輪子、引入外部開源組件等。

之所以我們使用線程池,實際上就是想實現多個線程的獨立運行,以一當百。這種也稱爲線程隔離指的是線程池隔離,核心業務線程與非核心業務線程隔離,一個請求出現問題不會影響到其他線程池。如Netty的主從多線程,Dubbo的Connection Ordered Dispatcher的線程模型(圖片來源於網絡)







 





但當我們的工作或需求複雜時,增加線程或線程池往往不是最明智的選擇,畢竟線程之間的通信過程以來的共享變量與環境耦合過於嚴重。此時我們通常會考慮將多個線程封裝到某個進程中,利用多個線程來時間複雜操作。

進程隔離

比如把項目拆分成一個一個的子項目,互相物理隔離,或使用命名空間、資源控制以及其他進程隔離技術進行隔離。如前後端分離項目、容器隔離。(圖片來源於網絡)





 

但無論我們的程序設計的如何優雅,總有一個繞不開的致命問題,機器纔是程序的實體,嚴重依賴硬件資源就是致命的問題。所以大家往往會選擇升級軟件架構,比如採用微服務架構,將程序與硬件資源進一步結構

集羣隔離

集羣部署與更新時我們目前日常開發中必不可少的流程之一,將應用部署到多個容器,使用集羣隔離開不同服務,使互相不影響,可以看作是進程隔離的進一步升級。(圖片來源於網絡)





 

集羣隔離示例圖



但這種方式受限於機器的部署環境,畢竟在地球上,一隻海鷗扇動翅膀就可能能夠永遠改變天氣變化。

機房隔離

更進一步,我們通常會把機器分不同的機房進行部署,如我們常用的廊坊與匯天機房。

從程序到機器,從機器到空間,雖然技術日新月異,我們仍然需要依賴這種樸素的方式抵禦風險。如果較真會發現,我們仍然可以繼續增大隔離性,但我們先到此爲止,我們可以再簡單的將視角從物理層面轉換到數據流量維度。

讀寫隔離

互聯網項目中大多是讀多寫少,我們常規的處理方式就是讀寫分離,一方面避免讀取邏輯對寫入邏輯的干擾,同時擴展讀的能力,提高性能,提高可用性。在這種架構下,核心的出發點就是數據與操作之間隔離,只是已通過不同技術手段完成。實際上,分庫分表、冷熱隔離等,都是具體的實現方式。(圖片來源於網絡)





 

熱點隔離

當我們用同樣的方式審視業務或流量入口時,仍然可以總結出一些規律,如將熱點業務獨立成系統或服務進行隔離,如秒殺,搶購。



3.3、業務實踐

上述討論的都是圍繞現有開發技術與經驗的探究,可以發現隔離原則確實無處不在,但無處不在並不等於一定存在,比如我們持續迭代更新的業務系統。

1、垂直機房改造

對於系統的可用性風險事故,給我印象最深的就是在22年剛入職時,就經歷過一次嚴重的線上事故,總的來說就是某個應用的機房掛了,且是機房硬件問題,導致研發人員束手無策,整個交易服務鏈路完全熔斷。事實上,在後續的斷網演練與混沌工程中,偶爾也會發現類似的問題。這類“黑天鵝事件”對系統的影響是致命的,所以歷經長時間的治理,我想jd的研發同學所負責的系統都應該已經完成垂直機房改造了。

時至今日,再也沒有發生過類似的問題了,這應該就是隔離原則最簡單最直接的體現了。

背景

跨機房容災即某機房完全斷網後業務不受影響,降低機房故障影響,提升跨機房容災能力。

技術方案

1)JSF垂直調用改造:服務端提供不同機房不同別名,調用方配置同機房別名調用;

2)NP掛載跨機房多VIP:跨機房多VIP 且 與負載均衡/服務容器IP所在同機房;

3)JIMDB讀垂直調用改造:廊坊應用容器讀廊坊jimdb節點;匯天應用容器讀匯天jimdb節點;不能採用讀隨機方式。

4)ES雙機房主備集羣;

5)應用跨多機房對等部署;

6)直接對接color上註冊的JSF服務修改成註冊HTTP服務。如果JSF直接對接合轍,按機房垂直調用原則在合轍配置不同服務別名即可。



2、es雙集羣改造

當我們用同樣的方式來審視我們的應用系統,我們同樣會發現一些風險。比如積理訂單的es雙集羣,對於積理訂單es而言,存儲着交易鏈路的訂單信息,提供外部系統訂單列表信息查詢的基礎服務,一向是重中之重,以至於我們在es之上的建立了一個專門提供es查詢和寫入應用服務。

訂單es在之前就是雙集羣,每個集羣都是一主兩從, 日常也有着均分流量配置,完備的降級切流預案。但致命的問題就在於,雙集羣都在某個機房之中。是的,類似於垂直機房改造前的風險,雖然從來沒有發生過,但這種風險存在是不可接受的。

所以在去年雙十一,我們啓動了es雙集羣改造工作,目前已經是兩套獨立機房的穩定集羣提供數據服務。

背景

積理訂單系統作爲黃金鍊路中的重要0級系統,其核心流程強依賴的ES爲單機房單集羣,容災能力弱,恢復能力差;因此對積理訂單ES系統做雙集羣改造及多種容災恢復策略,以提升系統可用性。

技術方案

上半部分是我們爲了兼容老數據所做的一些切流邏輯,下半部分則是垂直機房改造之後的效果。

在之前,積理訂單es應用會接受來自積理訂單中間件異步事件消息,通過不同消息軌跡分別寫入到不同集羣之中,使用消息體中的版本號作爲數據最終一致性的保障。

我們仍然沿用這種寫邏輯,重新在廊坊和匯天獨立申請了兩套es集羣服務。

而針對讀邏輯,我們進行了垂直機房與集羣調用的改造,保留了之前的百分比流量配置,同時增加了垂直互備調用,防止某一機房網絡抖動或事故導致垂直鏈路的可用性降低,增加了垂直互備調用邏輯。

如果有同學感興趣詳細的設計思路和實現細節,可以查看我們組童鞋編寫的這篇治理文章:ES高可用-雙集羣改造





 

容災讀策略使用
策略選擇 場景 備註
百分比模式 單邊機房性能受限 調低受限機房百分比
百分比模式 單邊機房掉線 全量切到正常機房
垂直調用互備模式 日常場景 減少毛刺抖動帶來的超時影響
垂直調用 高性能場景 就近調用、快速響應

3、流量隔離 - 分組

上面聊到的兩個案例實際上都是空間層面的隔離,可以發現我們的系統在嚴格的審視下,總能發現一些問題,同樣的,我們也可以切換視角到應用流量上。

積理訂單作爲全渠道黃金鍊路中的重要0級系統,即支持了線上業態,同事也承接着大量的線下業務流量,

但都是使用相同的代碼部署。一方面,日常需求的迭代更新中,很難保證代碼持續的可靠,這一點,前文已經有所描述。一旦某次線上或者線下業務需求的改造發生問題,也會導致整體鏈路不可用。更重要的是,線上與線下業態在流量峯值、及時性和業務模式上都存在很大區別,

所以這種場景下,針對流量的隔離就顯得十分重要。

背景

線下POS場景的訂單交易流程要求極高的可用性與及時性,爲了防止線上流量影響線下門店的即時消費,需要將流量進行區分,針對線下場景提供專用容器服務。除了積理訂單以外,快退、交易結算等都存在線上與線下分組隔離。

技術方案







 

4、數據隔離 - 冷熱數據歸檔

最後,我想以一個房間裏的大象作爲結尾。當我們在機房、應用、流量角度考慮系統的高可用時,通常會想,系統爲什麼之前不這麼做。事實上,我們的技術總是在進步的,而研發系統的架構也是在不斷實際的,有些問題可能也只有隨着業務的不斷豐富纔會暴露出來的,軟件系統如同隨着業務更新不斷生長的。

這個數據隔離的應用是訂單ums,這個應用實際上提供的功能十分簡單,甚至於寫入方只有訂單系統內部幾個系統寫入,保存着訂單全生命週期中的跟蹤信息,全稱是訂單全流程跟蹤信息。對外提供者簡單的查詢服務。甚至於很久都沒有需求改造,持續穩定的提供的服務,從沒有發生過線上問題和告警。

但去年的雙十一我們終於發現了這頭房間裏的大象,之所以發現,是因爲他已經擁有了1億條訂單跟蹤數據,讓我們不得不心驚膽戰的完成歸檔改造。

背景

1、 1000000000+條數據,數據量大

2、 日常調用頻繁,QPS-50/ms

因此設計做歸檔的處理,做冷熱隔離、熱庫表只保留90天內的訂單信息。

技術方案





 

三、結語

通過以上對日常開發與業務實踐的討論,我們會發現,隔離原則雖然無處不在,但並不是一定存在的;系統能穩定運行,但不會一直穩定運行。我想這也是研發同學的價值所在:持續的關注系統,持續的審視系統,持續的優化系統。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章