1. 程式人生 > >億級流量系統架構之如何設計全鏈路99.99%高可用架構【石杉的架構筆記】

億級流量系統架構之如何設計全鏈路99.99%高可用架構【石杉的架構筆記】

歡迎關注個人公眾號:石杉的架構筆記(ID:shishan100)

週一至週五早8點半!精品技術文章準時送上!


一、前情回顧

上篇文章(《億級流量系統架構之如何設計每秒十萬查詢的高併發架構》),聊了一下系統架構中的查詢平臺。

我們採用冷熱資料分離:

  • 冷資料基於HBase+Elasticsearch+純記憶體自研的查詢引擎,解決了海量歷史資料的高效能毫秒級的查詢
  • 熱資料基於快取叢集+MySQL叢集做到了當日資料的幾十毫秒級別的查詢效能。

最終,整套查詢架構抗住每秒10萬的併發查詢請求,都沒問題。

本文作為這個架構演進系列的最後一篇文章,我們來聊聊高可用這個話題。所謂的高可用是啥意思呢?

簡單來說,就是如此複雜的架構中,任何一個環節都可能會故障,比如MQ叢集可能會掛掉、KV叢集可能會掛掉、MySQL叢集可能會掛掉。那你怎麼才能保證說,你這套複雜架構中任何一個環節掛掉了,整套系統可以繼續執行?

這就是所謂的全鏈路99.99%高可用架構,因為我們的平臺產品是付費級別的,付費級別,必須要為客戶做到最好,可用性是務必要保證的!

我們先來看看目前為止的架構是長啥樣子的。


二、MQ叢集高可用方案

非同步轉同步 + 限流演算法 + 限制性丟棄流量

MQ叢集故障其實是有概率的,而且挺正常的,因為之前就有的大型網際網路公司,MQ叢集故障之後,導致全平臺幾個小時都無法交易,嚴重的會造成幾個小時公司就有數千萬的損失。我們之前也遇到過MQ叢集故障的場景,但是並不是這個系統裡。

大家想一下,如果這個鏈路中,萬一MQ叢集故障了,會發生什麼?

看看右上角那個地方,資料庫binlog採集中介軟體就無法寫入資料到MQ叢集了啊,然後後面的流控叢集也無法消費和儲存資料到KV叢集了。這套架構將會徹底失效,無法執行。

這個是我們想要的效果嗎?那肯定不是的,如果是這樣的效果,這個架構的可用性保障也太差了。

因此在這裡,我們針對MQ叢集的故障,設計的高可用保障方案是:非同步轉同步 + 限流演算法 + 限制性丟棄流量

簡單來說,資料庫binlog採集環節一旦發現了MQ叢集故障,也就是嘗試多次都無法寫入資料到MQ叢集,此時就會觸發降級策略。不再寫入資料到MQ叢集,而是轉而直接呼叫流控叢集提供的備用流量接收介面,直接傳送資料給流控叢集。

但是流控叢集也比較尷尬,之前用MQ叢集就是削峰的啊,高峰期可以稍微積壓一點資料在MQ叢集裡,避免流量過大,沖垮後臺系統。

所以流控叢集的備用流量接收介面,都是實現了限流演算法的,也就是如果發現一旦流量過大超過了閾值,直接採取丟棄的策略,拋棄部分流量。

但是這個拋棄部分流量也是有講究的,你要怎麼拋棄流量?如果你不管三七二十一,胡亂丟棄流量,可能會導致所有的商家看到的資料分析結果都是不準確的。因此當時選擇的策略是,僅僅選擇少量商家的資料全量拋棄,但是大部分商家的資料全量儲存。

也就是說,比如你的平臺使用者有20萬吧,可能在這個丟棄流量的策略下,有2萬商家會發現看不到今天的資料了,但是18萬商家的資料是不受影響,都是準確的。但是這個總比20萬商家的資料全部都是不準確的好吧,所以在降級策略制定的時候,都是有權衡的。

這樣的話,在MQ叢集故障的場景下,雖然可能會丟棄部分流量,導致最終資料分析結果有偏差,但是大部分商家的資料都是正常的。

大家看看下面的圖,高可用保障環節全部選用淺紅色來表示,這樣很清晰。


三、KV叢集高可用保障方案

臨時擴容Slave叢集 + 記憶體級分片儲存 + 小時級資料粒度

下一個問題,如果KV叢集掛了怎麼辦?這個問題我們還真的遇到過,不過也不是在這個系統裡,是在另外一個我們負責過的核心繫統裡,KV叢集確實出過故障,直接從持續好多個小時,導致公司業務都幾近於停擺,損失也是幾千萬級別的。

大家看看那個架構圖的右側部分,如果KV叢集掛了咋辦?那也是災難性的,因為我們的架構選型裡,直接就是基於kv叢集來進行海量資料儲存的,要是KV掛了,沒任何高可用保障措施的話,會導致流控叢集無法把資料寫入KV叢集,此時後續環節就無法繼續計算了。

我們當時考慮過要不要引入另外一套儲存進行雙寫,比如引入一套hbase叢集,但是那樣依賴會搞的更加的複雜,打鐵還需自身硬,還是要從自身架構來做優化。

因此,當時選擇的一套kv叢集降級的預案是:臨時擴容Slave叢集 + 小時級資料粒度 + 記憶體級分片儲存。

簡單來說,就是一旦發現kv叢集故障,直接報警。我們收到報警之後,就會立馬啟動臨時預案,手動擴容部署N倍的Slave計算叢集。

接著同樣會手動開啟流控叢集的一個降級開關,然後流控叢集會直接按照預設的hash演算法分發資料到各個Slave計算節點。

這就是關鍵點,不要再基於kv叢集存資料了,本身我們的Slave叢集就是分散式計算的,那不是剛好可以臨時用作分散式儲存嗎!直接流控叢集分發資料到Slave叢集就行了,Slave節點將資料留存在記憶體中即可。

然後Master節點在分發資料計算任務的時候,會保證計算任務分發到某個Slave節點之後,他只要基於本地記憶體中的資料計算即可。

將Master節點和Slave節點都重構一下,重構成本不會太高,但是這樣就實現了本地資料儲存 + 本地資料計算的效果了。


但是這裡同樣有一個問題,要知道當日資料量可是很大的!如果你都放Slave叢集記憶體裡還得了?

所以說,既然是降級,又要做一個balance了。我們選擇的是小時級資料粒度的方案,也就是說,僅僅在Slave叢集中儲存最近一個小時的資料,然後計算資料指標的時候,只能產出每個小時的資料指標。

但是如果是針對一天的資料需要計算出來的資料指標,此時降級過後就無法提供了,因為記憶體中永遠只有最近一個小時的資料,這樣才能保證Slave叢集的記憶體不會被撐爆。

對使用者而言,就是隻能看當天每個小時的資料指標,但是全天彙總的暫時就無法看到。


四、實時計算鏈路高可用保障方案

計算任務重分配 + 主備切換機制

下一塊就是實時計算鏈路的高可用保障方案了,其實這個之前給大家說過了,實時計算鏈路是一個分散式的架構,所以要麼是Slave節點宕機,要麼是Master節點宕機。

其實這個倒沒什麼,因為Slave節點宕機,Master節點感知到了,會重新分配計算任務給其他的計算節點;如果Master節點宕機,就會基於Active-Standby的高可用架構,自動主備切換。

咱們直接把架構圖裡的實時計算鏈路中的高可用環節標成紅色就可以了


五、熱資料高可用保障方案

自研快取叢集查詢引擎 + JVM本地快取 + 限流機制

接著咱們來看左側的資料查詢那塊,熱資料也就是提供實時計算鏈路寫入當日資料的計算結果的,用的是MySQL叢集來承載主體資料,然後前面掛載一個快取叢集。

如果出現故障,只有兩種情況:一種是MySQL叢集故障,一種是快取叢集故障。

咱們分開說,如果是MySQL叢集故障,我們採取的方案是:實時計算結果直接寫入快取叢集,然後因為沒有MySQL支撐,所以沒法使用SQL來從MySQL中組裝報表資料。

因此,我們自研了一套基於快取叢集的記憶體級查詢引擎,支援簡單的查詢語法,可以直接對快取叢集中的資料實現條件過濾、分組聚合、排序等基本查詢語義,然後直接對快取中的資料查詢分析過後返回。

但是這樣唯一的不好,就是快取叢集承載的資料量遠遠沒有MySQL叢集大,所以會導致部分使用者看不到資料,部分使用者可以看到資料。不過這個既然是降級 ,那肯定是要損失掉部分使用者體驗的。

如果是快取叢集故障,我們會有一個查詢平臺裡的本地快取,使用ehcache等框架就可以實現,從mysql中查出來的資料在查詢平臺的jvm本地快取裡cache一下,也可以用作一定的快取支撐高併發的效果。而且查詢平臺實現限流機制,如果查詢流量超過自身承載範圍,就限流,直接對查詢返回異常響應。


六、冷資料高可用保障方案

收集查詢日誌 + 離線日誌分析 + 快取高頻查詢

其實大家看上面的圖就知道,冷資料架構本身就比比較複雜,涉及到ES、HBase等東西,如果你要是想做到一點ES、HBase宕機,然後還搞點兒什麼降級方案,還是挺難的。

你總不能ES不能用了,臨時走Solr?或者HBase不能用了,臨時走KV叢集?都不行。那個實現複雜度太高,不合適。

所以當時我們採取的方法就是,對最近一段時間使用者發起的離線查詢的請求日誌進行收集,然後對請求日誌在每天凌晨進行分析,分析出來那種每個使用者會經常、多次、高頻發起的冷資料查詢請求,然後對這個特定的查詢(比如特殊的一組條件,時間範圍,維度組合)對應的結果,進行快取。

這樣就直接把各個使用者高頻發起的冷資料查詢請求的結果每天動態分析,動態放入快取叢集中。比如有的使用者每天都會看一下上週一週的資料分析結果,或者上個月一個月的資料分析結果,那麼就可以把這些結果提前快取起來。

一旦ES、HBase等叢集故障,直接對外冷資料查詢,僅僅提供這些提前快取好的高頻查詢即可,非高頻無快取的查詢結果,就是看不到了。


七、最終總結

上述系統到目前為止,已經演進到非常不錯的狀態了,因為這套架構已經解決了百億流量高併發寫入,海量資料儲存,高效能運算,高併發查詢,高可用保障,等一系列的技術挑戰。線上生產系統執行非常穩定,足以應對各種生產級的問題。

其實再往後這套系統架構還可以繼續演進,因為大型系統的架構演進,可以持續N多年,比如我們後面還有分散式系統全鏈路資料一致性保障、高穩定性工程質量保障,等等一系列的事情,不過文章就不再繼續寫下去了,因為文章承載內容量太少,很難寫清楚所有的東西。

其實有不少同學跟我反饋說,感覺看不懂這個架構演進系列的文章,其實很正常,因為文章承載內容較少,這裡有大量的細節性的技術方案和落地的實施,都沒法寫出來,只能寫一下大型系統架構不斷演進,解決各種線上技術挑戰的一個過程。

我覺得對於一些年輕的同學,主要還是瞭解一下系統架構演進的過程,對於一些年長已經做架構設計的兄弟,應該可以啟發一些思路,歡迎公眾號後臺給我留言,探討這些技術問題。

END



一大波微服務、分散式、高併發、高可用原創系列

文章正在路上,歡迎掃描下方二維碼,持續關注:


石杉的架構筆記(id:shishan100)

十餘年BAT架構經驗傾囊相授

推薦閱讀:

1、拜託!面試請不要再問我Spring Cloud底層原理

2、【雙11狂歡的背後】微服務註冊中心如何承載大型系統的千萬級訪問?

3、【效能優化之道】每秒上萬併發下的Spring Cloud引數優化實戰

4、微服務架構如何保障雙11狂歡下的99.99%高可用

5、兄弟,用大白話告訴你小白都能聽懂的Hadoop架構原理

6、大規模叢集下Hadoop NameNode如何承載每秒上千次的高併發訪問

7、【效能優化的祕密】Hadoop如何將TB級大檔案的上傳效能優化上百倍

8、拜託,面試請不要再問我TCC分散式事務的實現原理坑爹呀!

9、【坑爹呀!】最終一致性分散式事務如何保障實際生產中99.99%高可用?

10、拜託,面試請不要再問我Redis分散式鎖的實現原理!

11、【眼前一亮!】看Hadoop底層演算法如何優雅的將大規模叢集效能提升10倍以上?

12、億級流量系統架構之如何支撐百億級資料的儲存與計算

13、億級流量系統架構之如何設計高容錯分散式計算系統

14、億級流量系統架構之如何設計承載百億流量的高效能架構

15、億級流量系統架構之如何設計每秒十萬查詢的高併發架構