分布式架構(gòu):原理,設(shè)計(jì)與實(shí)戰(zhàn),目前公司每個(gè)月都要出賬,出賬就是每個(gè)月有要把之前的一個(gè)月的賬目盤算清楚,做到錯(cuò)誤的0容忍,一筆都不能錯(cuò),錯(cuò)一筆客戶都會(huì)找你,偏準(zhǔn)確性。4個(gè)9,5個(gè)9并不是說后面設(shè)計(jì)的,而是在開發(fā)之初就要考慮的。

分布式服務(wù)的發(fā)展歷程
- J2EE架構(gòu)
俗稱JEE。對(duì)于大概有5年以上工作經(jīng)驗(yàn)的老鐵,應(yīng)該都聽過這個(gè)名詞。基本分為3層。
- web容器
- EJB容器
- 數(shù)據(jù)庫(kù)和數(shù)據(jù)存取的ORM
那時(shí)候的容器之間都沒有進(jìn)行物理的隔離,都是部署在同一個(gè)jvm上的。所以久而久之,它們之間互相的耦合互相的依賴,業(yè)務(wù)之前有千絲萬縷的,添加和修改增加新的業(yè)務(wù)的時(shí)候,他們變的很復(fù)雜,經(jīng)常導(dǎo)致服務(wù)不可用。這個(gè)時(shí)代就是有了層次,但是層次之前沒有進(jìn)行物理的隔離。帶來了一些問題。

- SSH架構(gòu)
開源框架SSH = struts + spring + hibernate,實(shí)際上它跟JEE的架構(gòu)是基本相似的,也把組件分成了三層。
- struts MVC UI組件
- spring 業(yè)務(wù)組件,實(shí)現(xiàn)業(yè)務(wù)的邏輯
- ORM 對(duì)象管理映射層,連接數(shù)據(jù)庫(kù)的
那時(shí)候的SSH非常流行,因?yàn)槟莻€(gè)時(shí)期都是給傳統(tǒng)的行業(yè)和制造行業(yè)來做的系統(tǒng),在互聯(lián)網(wǎng)行業(yè)里面ssh架構(gòu)就不靈了。

- Web Service 架構(gòu)
互聯(lián)網(wǎng)行業(yè)偏向于服務(wù)化,最流行的微服務(wù)起源于服務(wù)化,服務(wù)化最早體現(xiàn)在web service,web service 以IBM為首的各大公司制定的標(biāo)準(zhǔn),webservice特點(diǎn)服務(wù)開發(fā)完畢后,不在部署在同一臺(tái)機(jī)器,同一個(gè)JVM上面,拆分成不同的服務(wù),例如圖中的web service1 ,web service2,web service3 它們3個(gè)各自有各自的角色,各自有各自的功能,服務(wù)和服務(wù)之前都是通過遠(yuǎn)程調(diào)用的方式來實(shí)現(xiàn)互相實(shí)現(xiàn)和交流的,遠(yuǎn)程調(diào)用是遵循已定的標(biāo)準(zhǔn),當(dāng)時(shí)標(biāo)準(zhǔn)是SOAP協(xié)議,這個(gè)協(xié)議是在http協(xié)議之上的,來傳輸xml來完成的。有了這些的服務(wù)。需要服務(wù)的發(fā)現(xiàn)機(jī)制,通過webservice的目錄來實(shí)現(xiàn)的。所有的服務(wù)對(duì)外提供服務(wù)的功能,需要在webservice注冊(cè)。發(fā)現(xiàn)服務(wù)UDDI,找到服務(wù)WSDL找到服務(wù)。這個(gè)時(shí)代服務(wù)主要的特點(diǎn)是:職責(zé)拆分,服務(wù)部署隔離,服務(wù)調(diào)用遵守協(xié)議。webservice定義的協(xié)議是非常重的,首先xml序列化,xml有冗余的標(biāo)簽,服務(wù)性能上不來的。webservice注冊(cè)通信化的服務(wù),通信化的注冊(cè)服務(wù)一定要保證高可用。在互聯(lián)網(wǎng)里面如果不是高可用的,服務(wù)也不是最優(yōu)化的。

- ESB架構(gòu)
企業(yè)服務(wù)總線,側(cè)重于企業(yè)服務(wù)總線。 上邊是提供的服務(wù),下面是數(shù)據(jù)庫(kù)數(shù)據(jù)源,消息隊(duì)列,大數(shù)據(jù),ERP。所有的服務(wù)和資源只要都進(jìn)入ESB中,就會(huì)進(jìn)行編排,完成特定的功能。這個(gè)時(shí)期,ESB功能進(jìn)行了拆分,也有各自的職責(zé),都進(jìn)行了拆分,在不同的物理機(jī),在不同JVM中。主要體現(xiàn)在可插拔,快速的添加刪除服務(wù),快速的加入資源。

- 微服務(wù)架構(gòu)
最流行的架構(gòu),跟傳統(tǒng)架構(gòu)是一脈相承的,并不是矛盾的。采用的是分層的概念,上層的服務(wù)依賴下層的服務(wù),基本兩層,第一層:業(yè)務(wù)服務(wù)一;第二層:業(yè)務(wù)服務(wù)2,3,4。上一層跟下一層是依賴的,但是不是循環(huán)依賴的。每個(gè)服務(wù)之間自己是用數(shù)據(jù)庫(kù)的,實(shí)際上數(shù)據(jù)庫(kù)緩存和消息隊(duì)列都是自治的,這就使微服務(wù)有自我管理的權(quán)限,微服務(wù)內(nèi)可以快速的消化需求,敏捷上線,提高開發(fā)和運(yùn)維的效率,微服務(wù)之前是通過遠(yuǎn)程的服務(wù)調(diào)用來先實(shí)現(xiàn)的。遠(yuǎn)程服務(wù)調(diào)用,并沒有特定的要求是通過使用restful還是rpc,要求服務(wù)之間一定要有契約,契約可以服務(wù)生產(chǎn)者提出,也可以服務(wù)消費(fèi)者提出的服務(wù)生產(chǎn)者契約,也可以是多個(gè)服務(wù)消費(fèi)者一起找服務(wù)的生產(chǎn)者提要求,服務(wù)生產(chǎn)者提供一個(gè)公共的契約,保證通信沒有問題的。例如:來了個(gè)需求,先進(jìn)行服務(wù)的拆分,拆分到不同的微服務(wù)里面,微服務(wù)有了良好的通信契約,不在管對(duì)外的功能,就在服務(wù)內(nèi)把需求消化掉了。上線和響應(yīng)市場(chǎng)也是非常敏捷的。微服務(wù)每個(gè)節(jié)點(diǎn)他們的拆分都是比較單一的,都是比較細(xì)的,職責(zé)單一后,專業(yè)的人干專業(yè)的事情,這樣很難犯錯(cuò)誤,這樣系統(tǒng)的可用性就提高起來了。

- 微服務(wù)的團(tuán)隊(duì)管理
團(tuán)隊(duì)其實(shí)也是自治的。微服務(wù)團(tuán)隊(duì)里面可能是有產(chǎn)品,運(yùn)營(yíng),測(cè)試,開發(fā)。如果系統(tǒng)分配到某個(gè)團(tuán)隊(duì)內(nèi),在團(tuán)隊(duì)內(nèi)的開發(fā)可以非常敏捷的溝通,很快的開發(fā)上線,并不需要跨團(tuán)隊(duì)的溝通,跨團(tuán)隊(duì)的協(xié)調(diào),回顧下當(dāng)初的SSH,公司分為UI組,開發(fā)組,測(cè)試組,DB人團(tuán)隊(duì)溝通,都不是微服務(wù)的團(tuán)隊(duì)導(dǎo)致溝通效率很低。所以這就是微服務(wù)倡導(dǎo)的敏捷,專業(yè)的人干專業(yè)的事。

- 分布式服務(wù)架構(gòu)的精髓
敏捷上線,微服務(wù)下的自治,有效的減少不可用的因素。服務(wù)化和微服務(wù)都使用了分而治之的思想,分布式服務(wù)和分布式系統(tǒng)架構(gòu)里面,無論是提高性能,提高吞吐量,提高敏捷性。

- 微服務(wù)架構(gòu)的痛點(diǎn)
- 一致性
強(qiáng)一致性和弱一致性
- 高性能
容量評(píng)估和性能測(cè)試
- 高可用
4個(gè)9和5個(gè)9
- 可擴(kuò)展
可修改,迭代新功能,可插拔
- 可伸縮
應(yīng)用層和資源層,隨著硬件投入的增加性能和能力相應(yīng)的增長(zhǎng)
- 安全性
防偷窺,防泄漏,防抵賴,防篡改,防中間人攻擊
保證分布式一致性的最佳方案
周朝的時(shí)候,分而治之,后來都不聽周王的話,導(dǎo)致不一致。不一致導(dǎo)致的痛點(diǎn)是很大的。如何去解決不一致的問題。線上趟過的坑和總結(jié)的經(jīng)驗(yàn)分享。
- 一致性原理
本質(zhì)上需要理解下面的3種,本身是什么,應(yīng)用的場(chǎng)景。

image.png
ACID,數(shù)據(jù)庫(kù)理論的時(shí)候,我們都學(xué)過ACID就是強(qiáng)一致性。四個(gè)名詞代表的是一個(gè)事務(wù)是不可以在進(jìn)行拆分的,要么都成功,要么都失敗。在傳統(tǒng)的數(shù)據(jù)庫(kù)里面都是單體的應(yīng)用,單體的應(yīng)用必須保持強(qiáng)一致性的,尤其是我們的關(guān)系型數(shù)據(jù)庫(kù)。猶豫在互聯(lián)網(wǎng)高并發(fā)的線上。用戶量非常大,上千,上萬,上億的,單體的服務(wù)架構(gòu)和單體數(shù)據(jù)庫(kù)很難撐起來這么大的量,所以就需要它們之前進(jìn)行分而治之,在網(wǎng)上進(jìn)行分開,進(jìn)行分開,分片。帶來的問題,當(dāng)網(wǎng)絡(luò)出現(xiàn)問題的時(shí)候,這些應(yīng)用是否可以正常的工作。這就引入了CAP原則。
CAP,之間肯定是網(wǎng)絡(luò)通信,一定要有分區(qū)容錯(cuò)性,也就是某個(gè)節(jié)點(diǎn)網(wǎng)絡(luò)不能正常的通信時(shí)。網(wǎng)絡(luò)斷了,或者閃斷的話,各自之間還要繼續(xù)的工作。P肯定是要有的。這個(gè)原則是如果三者只能選擇其中的二個(gè),P已經(jīng)必須要了,那就需要在C和A之間選擇一個(gè)。例如:網(wǎng)絡(luò)上有一份數(shù)據(jù),數(shù)據(jù)是通過復(fù)制來完成的。一份是主數(shù)據(jù),一份是從數(shù)據(jù),當(dāng)你存一份數(shù)據(jù)的時(shí)候到主數(shù)據(jù)的時(shí)候,同時(shí)也需要往從數(shù)據(jù)中存一份,如果從出現(xiàn)問題,是繼續(xù)還是返回給主,這就是一致性和可用性的解讀。如果主從必須保持一致,主從都存起來后才可以返回的話,那就保證一致性,可用性就不好,如果網(wǎng)絡(luò)出問題,就一致等待都一致才返回。不會(huì)在有限的時(shí)間內(nèi)返回給客戶端的請(qǐng)求,可用性就很差,所以一致性和可用性就是互斥的。如果是很快的返回客戶端,那就可能犧牲了一致性保持了可用性。總結(jié)就是在容錯(cuò)性的基礎(chǔ)之上,可用性和一致性是互斥的。不可兼得。
BASE,基本可用,中間有軟狀態(tài),最終保持了一致。基本可用是條件,最終保持一致是目標(biāo)。軟狀態(tài)就是事先的BASE的方法,就是我們要做一個(gè)事,達(dá)到目的中間的過程需要2,3個(gè)階段,做完一個(gè)階段記錄狀態(tài)信息,然后做第二個(gè)階段,我們可以從出問題的那個(gè)位置恢復(fù)到出問題的地方。互聯(lián)網(wǎng)上很多的高并發(fā)項(xiàng)目,都使用了分布式事務(wù)都進(jìn)行打折了,完成了最終一致性。使用了BASE原理,CAP限制了它不可能三者同時(shí)存在。
- 一致性協(xié)議
兩個(gè)階段的協(xié)調(diào)者

image.png
三階段的協(xié)調(diào)者

TCC(Try)

- 最終一致性
查詢模式

補(bǔ)償模式

異步確保模式

定期校對(duì)模式

可靠消息模式


image.png
- 服務(wù)交互的模式
同步模式

異步模式

image.png
消息模式

- 同步與異步的抉擇
盡量使用異步來替換同步操作
能用同步解決的問題,不要引入異步
- 超時(shí)模式
同步兩個(gè)狀態(tài)的接口超時(shí)

同步兩個(gè)狀態(tài)的內(nèi)部超時(shí)

同步三狀態(tài)的內(nèi)部超時(shí)

異步受理超時(shí)

消息隊(duì)列發(fā)送超時(shí)

消息對(duì)壘接收超時(shí)

- 補(bǔ)償?shù)牟┺?/li>

服務(wù)1調(diào)用服務(wù)2,如果服務(wù)2響應(yīng)服務(wù)1,并且告訴服務(wù)1消息我接收了,那么服務(wù)1的任務(wù)就結(jié)束了,如果服務(wù)2處理失敗,服務(wù)2應(yīng)該負(fù)責(zé)重試或者補(bǔ)償。在這種情況下,服務(wù)2通常先持久化消息后再告訴服務(wù)1接收成功,隨后服務(wù)2才開始處理持久的消息,避免服務(wù)進(jìn)程被傻吊丟失消息的情況。

服務(wù)1調(diào)用服務(wù)2,如果服務(wù)2沒有給出明確的接收響應(yīng),那么服務(wù)1應(yīng)該持久嘗試重試,知道服務(wù)2明確表達(dá)已經(jīng)接收消息,這種情況下,容易出現(xiàn)消息重復(fù),因此在服務(wù)2中通常要保證濾重或者冪等性。

- 緩存使用的一致性模式
緩存是用來加速的,犧牲了一致性,獲得高性能,只適合特殊場(chǎng)景。
保持?jǐn)?shù)據(jù)庫(kù)和緩存的強(qiáng)一致性是個(gè)偽命題
如果性能要求不是非常的高,盡量使用分布式緩存,而不是使用本地緩存,本地緩存可能你現(xiàn)在讀的時(shí)候本地是開,其實(shí)另一個(gè)時(shí)間其他人讀的是關(guān),你想想多可怕。
種緩存的時(shí)候一定種完全,如果緩存數(shù)據(jù)的一部分有效,一部分無效,寧可放棄種緩存,也不要把部分?jǐn)?shù)據(jù)中入緩存
通常情況下讀的順序要先緩存,后數(shù)據(jù)庫(kù),寫的順序要先數(shù)據(jù)庫(kù),后緩存
- 遷移開關(guān)的設(shè)計(jì)模式
新舊系統(tǒng)的遷移。
不要用統(tǒng)一配置開關(guān),開關(guān)是定義在某個(gè)業(yè)務(wù)上。在一個(gè)系統(tǒng)做濾重,比在多個(gè)系統(tǒng)做濾重簡(jiǎn)單。
不要用節(jié)點(diǎn)獨(dú)立的開關(guān)
遷移開關(guān)必須使用訂單開關(guān)
開關(guān)要用權(quán)限控制。開關(guān)的重要,特定經(jīng)驗(yàn)的人來操作。
開關(guān)要能開能關(guān)
遷移開關(guān)要大小力度都有
PS:了解分布式架構(gòu),是對(duì)自己從心智上的一種提升,敲代碼只是往下看,建議多往前方看看。架構(gòu)這條路不好走,需要多接觸,多趟多走,才能前方一路小平破。