以前寫了一篇秒殺系統的文章,最後給本身埋了分佈式事務的坑,而後不少讀者就要求我去寫分佈式事務,那做爲程序員屆的暖男,我一貫是有求必應的,就算是不睡覺我都要寫給大家看的!
由於分佈式事務是:分佈式 + 事務 = 分佈式事務。前端
理所固然的要先談談分佈式,而分佈式又得談談這個概念是如何演進得來的,所以做爲創做鬼才的我,就先來說講架構的演進,什麼叫分佈式?什麼是集羣?SOA、微服務這兩個東西的關係和區別,下篇再講分佈式事務。程序員
由於我發現我讀者大多都是學生或者跟我同樣剛畢業不久,那一直聽分佈式估計都聽膩了,估計都還不知道分佈式的一些細節和架構演進路線吧。
先來講個題外話,我一直追崇一個技術點不只要理解其原理,還須要知道這個技術點解決了哪些痛點,這些痛點又是由什麼引起的?這個技術還未誕生的時候是如何解決的?數據庫
也就是總體的演進過程,歷史脈絡。小程序
好比爲什麼須要HTTP?HTTP0.9爲什麼須要演進到HTTP1.0?進而又向1.一、2演進到最新要將Google開發的基於UDP的QUIC協議應用到HTTP3中。後端
搞懂這些前因後果相信你不只僅對HTTP會有更深層次的理解,對網絡也會有更加深入的認識。固然也不是說同樣東西一來就得全盤理清,有些東西仍是比較複雜的,只是說咱們要往這個方向去學。瀏覽器
這也是我一直以爲很重要的一個學習思想,知其然知其因此然,會讓你們更好的理解不少東西。服務器
好了,讓咱們回到今天的主題,我們先來看看通常架構的演進過程。網絡
爲何說通常呢?舉個例子,好比某線下龍頭企業,如今想開展網上相關業務,那麼有大批線下忠實用戶的支撐,而且自身錢包鼓鼓,人力財力都不缺。架構
那麼線上的軟件架構就得考慮清楚了,幾乎不可能按照初始階段來,固然也不能用力過猛,實際得靠架構師以及團隊實力進行權衡。
負載均衡
什麼是單體應用?簡單的說就是無論啥功能都往一個應用裏寫,好比電商系統。用戶功能、商品功能、訂單功能等等,都往一個應用裏寫。
在項目初期,小公司人力財力不足,急於拓寬市場,這種單體應用架構簡單粗暴,將全部的功能都打包在一個的應用中,直接部署。
本地開發調試方便,直接起一個項目,調試也是在一個進程內,沒有冗長跨進程的調用鏈,出錯可快速定位。
本地的函數調用,沒有網絡調用的開銷。
線上出了問題回滾這一個應用便可(這一點其實在某種程度上看是優勢,某種程度上看是缺點)。
總結的說就是開發、測試、部署方便,本地調用對於遠程調用性能較好。
系統耦合性高,致使開發效率低下。
一開始可能模塊結構還很清晰,隨着需求日益增加,不斷的添加新功能,代碼量巨增,模塊之間的邊界開始模糊,調用關係開始混亂,總體的代碼質量很是依賴我的水平。
假使某個同事水平較差,實現的代碼冗餘,邏輯混亂,這時候要在上面添加新功能或者修改老功能實際上是一件很困難的事情,你不能保證你修改的功能模塊不會影響到其餘功能。
並且代碼會有「破窗效應」(這裏其實不只僅是單體架構,對於全部架構來講都是如此,只是單體應用更大的龐大,業務界限不清晰,所以這種問題更容易被放大)。
有些人看到這就可能會說,這上面還說開發方便,這就又效率低下了?是的,過猶不及。
再好比一個新需求上線例如短信相關的,而且訂單也作了一些改造,可是短信功能出了 bug,須要回滾的是整個應用,訂單模塊冤啊,陪着一塊兒回滾。
我在老東家作電商活動,咱們上線一個需求可能涉及六、7個服務,回滾也得所有回滾,並且都是負載均衡的,那機器可能就是上百臺了。
語言單一,不能根據場景選擇更加合適的語言,例如要實現數據分析,應用的語言是 Java,那麼就不能利用到 Python 豐富的類庫。
系統的總體可靠性不高,什麼意思呢?仍是拿短信功能說事,新上的短信功能寫的有 bug,無論是堆棧溢出仍是死循環等等,核心的訂單等功能都會受到影響。所以你上線的功能有問題影響的不只僅是這個功能模塊,多是總體系統的癱瘓。
系統不易於擴展部署,假設你發現大家的商品查詢的流量特別大,頂不住就得加機器。由於是單體應用因此爲了商品查詢這一個功能,你須要在新加的機器上部署這一個應用,無法單獨爲這一個功能作定製化部署,對硬件資源有必定的浪費。
總結的說缺點就是隨着需求不斷增加,代碼結構日益複雜,各功能摻雜在一塊兒,系統耦合性高,模塊之間邊界維護很是依賴開發者的我的水平。
模塊之間常常會有公共功能難以劃分清楚,添加或修改功能困難,不肯定是否會影響到其餘模塊,全部功能都在一個進程內,某個功能出問題可能影響的就是整個應用,並且沒法根據特色場景選擇更加合適的語言去實現功能,技術單一。
隨着用戶的增加,沒法作到熱點功能單獨擴展,只能總體應用部署。
至此咱們已經明白了單體應用架構的優缺點,能夠看出初始階段單體應用優勢突出,隨着需求和用戶的增加漸漸的單體應用頂不住,缺點在不斷的放大。
也就是說你的產品須要發展到必定的階段,單體應用纔會頂不住。在這以前單體應用是你的最佳選擇。
你要是說個人產品確定頂的,因此一開始就大刀闊斧的設計,單體應用太 low 堅定不用。
能夠的,秀出你的花樣,你有你的 Young。
咱們再來看下單體應用通常的架構圖,注意單體應用不是真的就線上部署一個,好歹得兩臺,互相 backup 下,不能太虎一臺頂。
又過了一段時間,你發現大家還須要開發手機版。因而大家的架構又變成下圖所示的樣子。
沒錯,爲了讓每一個端不會相互影響,粗暴的拷貝現有的應用,稍加修改便可爲手機版和小程序提供服務,你會發現不少功能代碼都是重複的。這時候來個需求你改的就是多份代碼了。
又過了段時間你已經強烈感覺到單體應用所帶來的痛點,這證實你的產品發展的不錯,一開始確定會忍,繼續忍,終有一天你會一拍桌子!來開個會我們得還債了。
理所固然的你會根據不一樣業務拆分出不一樣的服務,而且會整理出當前公共的功能變成一個公共服務,每一個服務獨立部署,獨立運行,代碼進行了物理隔離,一個小團隊維護一個服務或多個服務。
而且通常而言服務化了,數據庫也會拆分出來每一個服務維護本身的數據庫,數據庫之間的數據經過接口傳遞,而再也不是直接訪問。
此時你的系統變成了下圖所示的樣子。
那如今解決了單體應用什麼問題?
系統的耦合度下降,模塊之間的邊界清晰,都按業務物理隔離了。
在必定的措施下(下文會提到),系統總體可靠性變高。
技術選型豐富,不一樣的服務能夠利用不一樣的技術或語言實現,例如數據分析服務能夠用 Python 實現,一些底層的服務團隊說我要用 GO,那就用 GO 唄。
可根據服務擴展部署,商品服務訪問量特大,那咱們就單單給商品服務擴容,增長機器,其餘服務照舊。
這就是微服務了。
好像微服務架構解決了單體應用的全部痛點啊?別急上面只是微服務的一部分,真正的微服務架構還須要包含不少東西,微服務是解決的單體應用的痛點,可是也引入了新的痛點!
服務化了以後上線某個需求,若是是單個服務內的不影響其它服務的你會感到很舒服,若是這個改動是接口層面的改動,涉及到多個服務,你就會以爲有點難受了。
上線以前須要定製好服務上線的順序,定製好每一個服務的回滾計劃,涉及到每一個團隊之間的合做,上線再也不是一個簡單的打包、部署的過程。
出了問題也不是一個簡單回滾的過程,而多是各個團隊分別回滾各自的服務。若是你本身的服務出了問題你會很焦慮,別的團隊都等着。若是別的團隊出了問題你也焦慮,怎麼還沒好啊。
你還會發現本地開發若是依賴別的服務會異常的難受,特別是你依賴的服務還依賴別人的服務,調試、測試將變的複雜。
並且你會發現調用鏈路變長,調用增長了網絡的開銷,性能變差。並且出錯難以定位問題來源。所以你須要引入分佈式鏈路追蹤服務來定位問題。
還須要引入ELK來方便日誌的查看,分析問題。
爲了可以動態擴容,你的服務須要自動註冊且能被自動發現,所以須要個註冊中心。
網絡之間的調用較爲不可靠,所以還須要讓調用有重試機制,防止其餘服務出 bug 或其餘緣由瘋狂調用你的服務,還須要有限流措施。爲了防止一個服務掛了致使總體的雪崩須要有熔斷措施。
爲了在特殊時候例如大促的時候讓出硬件資源給核心功能,還須要有降級策略。
上面說的重試、限流、熔斷、降級就是上文提到的必定措施下,可靠性變高。
並且每一個服務都須要配置,所以還得有個配置中心,來作統一管理。
服務太多了,調用關係複雜爲了對調用者更加的友好,而且還須要對調用進行權限等控制,所以須要有個網關,對外暴露統一的接口,固然想限流什麼的能夠在網關實現。
固然總體的監控是必不可少的,對全部的服務都須要作到全面的監控。
其餘的還有啥DevOps、容器等等。
能夠看到服務化以後須要引入太多太多的東西,有人可能說你這也就才幾個服務啊,我上面的服務其實能夠再細分。
例如商品的修改和寫入動做相比較於商品的瀏覽訪問量確定少不少,那我就將商品的瀏覽再剝離出來單獨作一個服務,這樣便於擴容。
這用戶量上來,訪問量增長這樣的服務剝離你會發現愈來愈多,服務的數量到時候就上來了,並且需求也會不斷增長,推薦服務啊、搜索服務啊等等不少不少,只是爲了簡便都沒列出來。
上面提到的那些服務於微服務的組件也得部署,也得保證可靠性...你看這系統就愈來愈複雜了,因此服務化以後解耦了業務,卻又融入了非業務相關的東西。
不過服務化實際上是一個天然的結果,就像咱們平時去的辦事大廳會根據服務類別劃分紅不一樣的服務窗口,爲了辦一件事情我能可能須要在各個窗口之間來回走動,這對應的不就是調用鏈路長嘛?走動的耗時等於咱們調用的網絡開銷。
因此說微服務架構是發展到一個階段天然而然的演進產物,早在微服務這個概念被提出以前,不少公司就已是這樣乾的了。
我上面提到的實際上是微服務1.0架構,而微服務2.0就是爲了將非業務功能剝離出來而提出的,將服務治理的功能放在 SideCar 即邊車上,使得開發者專一於應用業務的開發,進而演進出 Service
Mesh 即服務網格架構。
談到微服務你會發現 SOA 這個名詞常常伴隨着出現。
關於SOA和微服務我查閱了不少資料,不過對於這兩個名詞的解釋都各執一詞,沒有一個統一的答案。今天我就說說個人理解,拋磚引玉,有紕漏之處,敬請指正。
SOA,全稱 Service-Oriented Architecture即面向服務的架構。說到SOA就離不開 ESB,全稱Enterprise Service Bus。SOA和微服務同樣都是面向服務的。
能夠看到 SOA 架構經過企業服務總線進行交互,也就是說中心化,須要按照總線的標準進行開發改造,而微服務是去中心化的。
其實咱們能夠抓到關鍵字企業,SOA 我認爲是企業級別的面向服務概念,而微服務是應用級別的概念。
兩種都是面向服務,只是 SOA 注重的是企業資源的重複利用,把企業的各個應用經過 ESB 進行整合。
而微服務注重的是應用級別的服務劃分,使得應用內服務邊界清晰,易擴展。
這二者實際上是兩個方向的面向服務,互不衝突。還能是包容的結構,以下圖所示
分佈式能夠認爲是經過網絡鏈接多個組件而造成的系統。
廣義上說先後分離的應用就能算分佈式,前端的 js 代碼在瀏覽器跑着,後端的代碼在服務器跑着,兩種不一樣的組件協力對外提供服務構成分佈式。
而咱們常提到的分佈式是狹義上的,指代不一樣的組件經過協做構成的系統。
而集羣常指的同一個組件多實例而構成邏輯上的總體。
這兩個概念不衝突,分佈式系統裏面能夠包含集羣,像咱們的商品服務就能夠是集羣部署。
今天主要簡述了下架構的演進,單體應用的優缺點以及微服務的優缺點。
再談了談SOA 和微服務之間的區別,以及分佈式和集羣的區別。
說了這麼多,也不知道有沒有說清楚,我的能力有限,若是有紕漏,敬請指正,分佈式事務也在瘋狂爆肝中。
我是敖丙,你知道的越多,你不知道的越多,咱們下期見!