分散式系統的架構思路
在網際網路大行其道的今天,各種分散式系統已經司空見慣。搜尋引擎、電商網站、微博、微信、O2O平臺。。凡是涉及到大規模使用者、高併發訪問的,無一不是分散式。但不管那種業務,不管何種分散式系統,有一些基本的思想還是相通的。本文將對這些基本思想進行一個梳理彙總。
分拆
系統分拆
微信的架構師說過一句話:“大系統小做“。對於一個大的複雜系統,首先想到的就是對其分拆,拆成多個子系統。每個子系統自己的儲存/Service/介面層,各個子系統獨立開發、測試、部署、運維。
從團隊管理角度講,也可以不同團隊用自己熟悉的語言體系,團隊之間基於介面進行協作,職責清晰,各司其職。
子系統分拆
拆成子系統之後,子系統內部又可以分層,分模組。當然,這裡“系統“,“子系統“,“層“,“模組“ 都只是一個相對概念。在一個系統裡面,某個模組複雜到一定程度,會把它抽出來,單獨做成一個系統;而在初期,很大簡單模組,可能不回拆分,集中在一個系統裡面。
這就像一個生物組織,自身是在不斷成長、演化、有分有合,不斷變化發展的。
儲存分拆
Nosql:對於Nosql資料庫,比如MongoDB,其天生就是分散式的,很容易實現資料的分片。
Mysql: 對於Mysql,或者其它關係型資料庫,就會設計到分庫分表。而分庫分表,就會涉及到幾個關鍵性的問題:切分維度,join的處理,分散式事務
計算分拆
計算的分拆有2種思路:
資料分拆:一個大的資料集,拆分成多個小的資料集,平行計算。
比如大規模資料歸併排序
任務分拆:把一個長的任務,拆分成幾個環節,各個環節平行計算。
Java中多執行緒的Fork/Join框架,Hadoop中的Map/Reduce,都是計算分拆的典型框架。其思路都是相似的,先分拆計算,再合併結果。
再比如分散式的搜尋引擎中,資料分拆,分別建索引,查詢結果再合併。
併發
最常見的就是多執行緒,儘可能提高程式的併發度。
比如多次rpc順序呼叫,通過非同步rpc轉化為併發呼叫;
比如資料分片,你的一個Job要掃描全表,跑幾個小時,資料分片,用多執行緒,效能會加快好幾倍。
快取
快取大家都不陌生,遇到效能問題,大家首先想到的就是快取。關於快取,一個關鍵點就是:快取的粒度問題。
比如Tweet的架構,快取的粒度從小到大,有Row Cache, Vector Cache, Fragment Cache, Page Cache。
粒度越小,重用性越好,但查詢需要多次,需要資料拼裝;
粒度越大,越容易會失效,任何一個小的地方改動,都可能造成快取的失效。
線上計算 vs. 離線計算 / 同步 vs. 非同步
在實際的業務需求中,並不是所有需要都需要完全實時的:
比如內部針對產品、運營開發的各種報表查詢、分析系統;
比如微博的傳播,我發了一個微博,我的粉絲延遲幾秒才看到,這是可以接受的,因為他並不會注意到晚了幾秒;
比如搜尋引擎的索引,我發了一篇部落格,可能幾分鐘之後,才會被搜尋引擎索引到;
比如支付寶轉帳、提現,也並非這邊轉出之後,對方立即收到;
。。。
這類例子很多。這種“非實時也可以接受“的場景,就為架構的設計贏得了充分的迴旋餘地。
因為非實時,我們就可以做非同步,比如使用訊息佇列,比如使用後臺的Job,週期性處理某類任務;
也因為非實時,我們可以做讀寫分離,讀和寫不是完全同步,比如Mysql的Master-Slave。
全量 + 增量
全量/增量其實也是線上/離線的思路:
比如搜尋引擎的全量索引 + 增量索引,前者是為了吞吐,後者為了實時;
比如OceanBase資料庫,每次更新存在一個小表裡面,定期merge;
Push vs. Pull
在所有分散式系統中,都涉及到一個基本問題:節點之間(或者2個子系統之間)的狀態通知。比如一個節點狀態變更了,要通知另外一個節點,都有2種策略:
Push: 節點A狀態變了, push給節點B
Pull: 也就是輪詢。節點B週期性的去詢問節點A的狀態。
這個問題不光出現在分散式系統中,可以說是編寫程式碼的一個基本問題。對應到物件導向的程式設計中,也就是常說的“雙向關聯”這種耦合問題。
A呼叫B,B再回撥A,這種情形,在系統開發中經常出現。再複雜一點,多個模組之間,彼此呼叫,呼叫關係跟蜘蛛網一樣。
這個問題的出現,就和Push/Pull的策略密切相關:
A呼叫B,那邏輯就會寫在B這邊;B呼叫A,邏輯就會寫在A這邊。所以是採用主動呼叫的pull方式,還是回撥的push方式,會嚴重影響職責在各個模組或者子系統裡面的分配。
批量
批量其實也是線上/離線的一種思想,把實時問題,轉化為一個批量處理的問題,從而降低對系統吞吐量的壓力
比如Kafka中的批量發訊息;
比如廣告扣費系統中,把多次點選累積在一起扣費;
。。
重寫輕讀 vs 重讀輕寫
重寫輕讀,本質就是“空間換時間“。你不是計算起來耗時,延遲高嗎,那我可以提前計算,然後儲存起來。取的時候,直接去取。
我們通常對Mysql的用法,都是重讀輕寫,寫的時候,簡單;查的時候,做複雜的join計算,返回結果。這樣做的好處是容易做到資料的強一致性,不會因為欄位冗餘,造成資料的不一致。但是效能可能就是問題。
而如果採用重寫輕讀,怎麼做呢?你不是要看Feeds嗎,那就為每個人準備一個Feeds,或者說收件箱。某個人發了微博之後,把他的微博擴散到所有人的收件箱,這個擴散是非同步的,在後臺擴散。這樣每個人看自己的Feeds的時候,直接去自己的收件箱取就可以了。
讀寫分離
同樣,對傳統的單機Mysql資料庫,讀和寫是完全同步的。寫進去的內容,立馬就可以讀到。
但在很多業務場景下,讀和寫並不需要完全同步。這個時候,就可以分開儲存,寫到一個地方,再非同步的同步到另一個地方。這樣就可以實現讀寫分離。
比如Mysql的Master/Slave就是個典型,Slave上面的資料並不是和Master實時同步的;
再比如各種報表分析,OLTP/OLAP,線上/線下資料分離,線上資料定期同步到Hive叢集,再做分析。
動靜分離
動靜分離的典型例子就是網站的前端,動態的頁面,放在web伺服器上;靜態的css/jss/img,直接放到CDN上,這樣既提高效能,也極大的降低伺服器壓力。
按照這個思路,很多大型網站都致力於動態內容的靜態化,靜態化之後,就可以很容易的快取。
冷熱分離
比如定期把mysql中的歷史資料,同步到hive
限流
現在很多電商都會有秒殺活動,秒殺的一個特點就是商品很少,但短時間內流量暴增,伺服器完全處理不了這麼多請求。
應對這類問題的一個基本思路就是限流,既然處理不了那麼多請求,既然很大人進去了,也是搶不到的。那索性不要放那麼多人進去。
這個和我們日常生活中,節假日,某個景點人數過多,限制人流量是同樣的道理。
服務熔斷與降級
服務降級是系統的最後一道保險。在一個複雜系統內部,一個系統往往會呼叫其它很大系統的服務。在大流量的情況下,我們可能會在保證主流程能正常工作的情況下,對其它服務做降級。
所謂降級,也就是當某個服務不可用時,乾脆就別讓其提供服務了,直接返回一個預設的結果。雖然這個服務不可用,但它不至於讓整個主流程癱瘓,這就可以最大限度的保證核心系統可用。
CAP理論
上面講的各種思想,用一個更大的思想來概括的話,就是CAP。
Consistency:資料一致性,這個很容易理解,就是沒有髒資料。我們知道,在Mysql中有一致性的概念,比如參照完整性約束、事務等。但這裡的C主要特指同1份資料的多個備份之間的一致性。
Availability:可用性有2重意思,一個是說穩定性,服務可用,不會掛;另外一個是效能,也就是要快,如果延遲很高,經常超時,那和掛了也就區別不大了。
Partition tolerance(分割槽容錯性):分割槽,其實指網路分割槽。當你把資料從1個物理裝置,分到多個物理裝置之後,裝置之間必然是通過網路進行通訊。這就會遇到網路分割槽,也就是典型的“2將軍問題“,網路超時時間不定。學術上有個詞,叫“非同步通訊環境“。
以前說CAP理論,說對於一個分散式系統,上面3個,只能同時滿足2個。但這個其實不準確,P其實一定存在,是你避免不了的。能做的,其實主要是在C和A之間權衡。
歡迎大家一起交流二零四二八四九二三七
比如拿Mysql來說,它的C最強,A次之,P最弱。如果你為了A,給資料做冗餘,比如重寫輕讀,那C就很難保證;為了P,給資料做分庫分表,那就做不了事務;
比如Nosql,P最強,可以很好的做資料拆分,但C就不夠,做不了事務;
比如微博系統,對C的要求降低,就可以加很多快取,提高A;資料分片,提高P;
而支付,交易轉帳,對C的要求很高,就不能簡單的用Cache來提高效能
最終一致性
前面提到,在分散式系統中,因為資料的分拆,服務的分拆,強一致性就很難保證。這個時候,用的最多的就是“最終一致性“。
強一致性,弱一致性,最終一致性,是一致性的幾個不同的等級。在傳統的關係型資料庫中,通過事務來保證強一致性。
但在分散式系統中,通常都會把強一致性折中成最終一致性,從而變相的解決分散式事務問題。
最終一致性的實現,通常都需要一個高可靠的訊息佇列。
如果你現在在JAVA這條路上掙扎,也想在IT行業拿高薪,可以參加我們的訓練營課程,選擇最適合自己的課程學習,技術大牛親授,7個月後,進入名企拿高薪。我們的課程內容有:Java工程化、高效能及分散式、高效能、高架構、效能調優、Spring,MyBatis,Netty原始碼分析和大資料等多個知識點。如果你想拿高薪的,想學習的,想就業前景好的,想跟別人競爭能取得優勢的,想進阿里面試但擔心面試不過的,你都可以來,q群號為:835638062
相關文章
- HDFS架構指南(分散式系統Hadoop的檔案系統架構)架構分散式Hadoop
- 分散式系統架構筆記分散式架構筆記
- 分散式系統架構的冰與火分散式架構
- 什麼是分散式系統!以及分散式系統架構的優缺點!分散式架構
- 分散式系統的那些事兒 - SOA架構體系分散式架構
- 單元化架構,分散式系統的新王!架構分散式
- 現代分散式系統架構的權衡分析分散式架構
- 理解分散式系統中的快取架構(下)分散式快取架構
- 理解分散式系統中的快取架構(上)分散式快取架構
- 程式設計體系結構(09):分散式系統架構程式設計分散式架構
- 架構師職業迴歸:分散式系統架構師 - Leon架構分散式
- 大型分散式網站架構:快取在分散式系統中的應用分散式網站架構快取
- 淺談大型分散式Web系統的架構演進分散式Web架構
- 系統架構效能優化思路架構優化
- 分散式重複提交問題架構設計思路分散式架構
- 杉巖PACS影像系統分散式儲存架構分散式架構
- 從Elasticsearch來看分散式系統架構設計Elasticsearch分散式架構
- 分散式系統架構之構建你的任務排程中心分散式架構
- 美團即時物流的分散式系統架構設計分散式架構
- 深入理解分散式系統中的快取架構(下)分散式快取架構
- 億級流量架構之分散式事務思路及方法架構分散式
- 分散式架構的概述分散式架構
- 架構 秒殺系統優化思路架構優化
- 秒殺系統架構優化思路架構優化
- Java架構師面試題全集:Java基礎+技術框架+系統架構+分散式系統Java架構面試題框架分散式
- 整合spring cloud雲架構 --spring cloud分散式系統中實現分散式鎖SpringCloud架構分散式
- 分散式系統架構1:共識演算法Paxos分散式架構演算法
- 軟體系統的架構演進以及叢集和分散式架構分散式
- MyCat 啟蒙:分散式系統的資料庫架構演變分散式資料庫架構
- 基於golang分散式爬蟲系統的架構體系v1.0Golang分散式爬蟲架構
- 分散式WebSocket架構分散式Web架構
- 分散式系統架構與雲原生—阿里雲《雲原生架構白皮書》導讀分散式架構阿里
- 常見開源分散式檔案系統架構對比分散式架構
- 分散式架構知識體系必讀分散式架構
- 億級流量系統架構之如何設計高容錯分散式計算系統【石杉的架構筆記】架構分散式筆記
- 淺談架構-從傳統走向分散式架構分散式
- 分散式架構和微服務架構的區別分散式架構微服務
- ClickHouse 分散式架構(qbit)分散式架構