分佈式架構基本思想彙總(思惟方式)

在互聯網大行其道的今天,各類分佈式系統已經司空見慣。搜索引擎、電商網站、微博、微信、O2O平臺。。凡是涉及到大規模用戶、高併發訪問的,無一不是分佈式。css

關於分佈式系統,並無一個標準答案,說某某架構必定是最好的。不一樣的業務形態所面對的挑戰不同,使用的架構設計也不同,一般都須要具體業務具體分析。前端

但無論那種業務,無論何種分佈式系統,有一些基本的思想仍是相通的。本文將對這些基本思想進行一個梳理彙總。mysql

分拆web

系統分拆sql

微信的架構師說過一句話:「大系統小作「。對於一個大的複雜系統,首先想到的就是對其分拆,拆成多個子系統。每一個子系統本身的存儲/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,按一般的mysql的作法,我要先去查我關注的全部的人,而後把全部人的消息排序,分頁返回。很顯然,在大數據量下,這個會很耗時。

而若是採用重寫輕讀,怎麼作呢?你不是要看Feeds嗎,那就爲每一個人準備一個Feeds,或者說收件箱。某我的發了微博以後,把他的微博擴散到全部人的收件箱,這個擴散是異步的,在後臺擴散。這樣每一個人看本身的Feeds的時候,直接去本身的收件箱取就能夠了。

讀寫分離

一樣,對傳統的單機Mysql數據庫,讀和寫是徹底同步的。寫進去的內容,立馬就能夠讀到。

但在不少業務場景下,讀和寫並不須要徹底同步。這個時候,就能夠分開存儲,寫到一個地方,再異步的同步到另外一個地方。這樣就能夠實現讀寫分離。

好比Mysql的Master/Slave就是個典型,Slave上面的數據並非和Master實時同步的;

再好比各類報表分析,OLTP/OLAP,線上/線下數據分離,線上數據按期同步到Hive集羣,再作分析。

若是想學習Java工程化、高性能及分佈式、深刻淺出。微服務、Spring,MyBatis,Netty源碼分析的朋友能夠加Java進階羣:582505643,羣裏有阿里大牛直播講解技術,以及Java大型互聯網技術的視頻免費分享給你們。

動靜分離

動靜分離的典型例子就是網站的前端,動態的頁面,放在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來提升性能

最終一致性

前面提到,在分佈式系統中,由於數據的分拆,服務的分拆,強一致性就很難保證。這個時候,用的最多的就是「最終一致性「。

強一致性,弱一致性,最終一致性,是一致性的幾個不一樣的等級。在傳統的關係型數據庫中,經過事務來保證強一致性。

但在分佈式系統中,一般都會把強一致性折中成最終一致性,從而變相的解決分佈式事務問題。

典型的轉賬的例子,A給B轉賬1萬塊錢,A的帳號扣1萬,B的帳號加1萬。但這2步未必須要同時發生, A的扣完以後,B的帳號上面未必立馬就有,但只要保證B最終能夠收到就能夠了。

最終一致性的實現,一般都須要一個高可靠的消息隊列。關於這個,網上有各類分享文章,後續也會對這個問題單獨闡述。

分享一下新一波資料,都是本身在各個平臺上找到而後集合到一塊兒的。


相關文章
相關標籤/搜索