微服務是一個軟件架構模式,對微服務的討論大多集中在容器或其他技術是否能很好的實施微服務這些方面实撒。
? ? ? 本文將從以下幾個角度來和大家分享在微服務架構下進行數(shù)據(jù)設計需要關注的地方,旨在幫助大家在構建微服務架構時,提供一個數(shù)據(jù)方面的視角:
什么是微服務
微服務的優(yōu)勢及架構特點
微服務架構下的數(shù)據(jù)設計
一個適合微服務架構的數(shù)據(jù)庫
什么是微服務
? ? ? 按照 Martin Fowler 的定義知态,微服務是一個軟件架構模式捷兰,通過開發(fā)一系列的小型服務的方式來實現(xiàn)一個應用。每一個這樣的小服務通常都是運行在自己的進程里面负敏,并且通過輕量級的HTTP API 方式進行通訊贡茅。
這些服務通常會以業(yè)務模塊為界限,能夠被單獨開發(fā)部署其做,往往都會用自動化的部署工具來進行產(chǎn)品的發(fā)布顶考。通過使用微服務方法,大公司可以更快推出新產(chǎn)品和服務妖泄,使得開發(fā)團隊與業(yè)務目標保持一致驹沿。
微服務的優(yōu)勢
? ? ? 微服務方法體現(xiàn)出許多優(yōu)勢,包括更快的上線時間浮庐、靈活性甚负、彈性柬焕、一致性以及相對更低的成本审残。
更快的上線時間
? ? ? 實施微服務架構可以使組織更快地將應用程序推向市場。對整體應用程序的更改(即使很小)需要重新部署整個應用程序堆棧斑举,從而引入風險和復雜性搅轿。
? ? ? 相反,服務的更新可以立即提交富玷、測試和部署璧坟,對個別服務的更改不會影響系統(tǒng)的其他部分。
更好的靈活性和可擴展性
? ? ? 微服務方法在擴展應用程序時也提供了靈活性赎懦。單片應用程序要求整個系統(tǒng)(及其所有功能)同時擴展雀鹃。
? ? ? 使用微服務,只需要縮放需要額外性能的組件或功能励两±杈ィ可以通過部署更多微服務實例來擴展服務范圍,從而實現(xiàn)更有效的容量規(guī)劃并降低軟件許可成本当悔,從而降低總體擁有成本傅瞻。
彈性
使用單體應用程序時,組件的故障可能會危及整個應用程序盲憎。在微服務中嗅骄,每項服務都是隔離的,以防止級聯(lián)失敗導致整個系統(tǒng)崩潰饼疙。如果單個微服務的所有實例均失敗溺森,則整體服務可能會降級,但其他組件仍可提供有價值的服務。
更容易的規(guī)钠粱化
微服務使技術團隊能夠與組織需求保持一致澡罚,并且可以調(diào)整團隊的大小以匹配所需的任務。通常肾请,微服務團隊規(guī)模較小留搔,但是跨部門(如一般涵蓋Ops、Dev铛铁、QA)蚕甥,并專注于整個應用程序的單個組件。
通過提供對個人服務的所有權耻陕,而不是功能區(qū)域袁串,微服務還可以打破團隊之間的孤島,并改善協(xié)作倍权。這種方法對于分布式和遠程團隊尤其強大掷豺。 例如,不同地點的團隊可以獨立發(fā)布和部署功能薄声。
微服務的技術特點
讓我們通過一個例子來了解微服務架構的技術特點当船。聯(lián)邦銀行的架構師 Jonnathan 非常不喜歡他的產(chǎn)品經(jīng)理 Mandy,因為他覺得 Mandy 永遠有無窮無盡的想法要實現(xiàn)默辨,搞得他成天就在不斷地修改代碼德频。
但是 Mandy 是老板的紅人,而且用戶對產(chǎn)品的反響也不錯缩幸,所以很多時候他只能默默的服從壹置。這一天 Mandy 又成功的說服了老板要在他們的客戶體驗提升項目中增加輿情分析和 AI 客戶服務模塊,希望通過對社交媒體上有關聯(lián)邦銀行的所有評論進行實時的監(jiān)控和分析來及時發(fā)現(xiàn)聯(lián)邦銀行的產(chǎn)品反饋或者用戶體驗問題表谊。
Jonnathan已經(jīng)預感到了這樣前所未有的應用場景钞护,會有太多的未知和太多的改變,于是這次決定嘗試使用 Microservices 來構建這個應用爆办。這個是 Jonnathan 設計的架構难咕,系統(tǒng)要求對客戶的社交賬號,如 Facebook押逼、Twitter步藕、Google+ 及 Snapchat 公開的信息及評論進行收集,并在某些合適的時候使用 AI 技術直接和用戶通過社交工具進行互動挑格。
在上圖這個架構里面咙冗,Jonnathan 把4個不同社交媒體的數(shù)據(jù)采集和交互用 4 個獨立的模塊進行實現(xiàn)。并用一個 Feed Merge 服務漂彤,一個 Aggregate Service 把 4 個類似功能的微服務模塊的數(shù)據(jù)和功能進行整合雾消,提供給分析平臺使用灾搏。
? ? ? 這里面每一個服務按照微服務的架構,每一個都是單獨部署立润,在一個獨立的容器內(nèi)執(zhí)行狂窑,并使用自己的一個數(shù)據(jù)庫。
果不其然桑腮,系統(tǒng)上線一段時間后泉哈,Mandy 說 Google+ 上面幾乎沒有什么活動,不值得繼續(xù)維護這樣的一套系統(tǒng)破讨。Jonnathan 這次毫無抱怨丛晦,直接把負責 Google+ 的容器停了,沒有需要任何代碼改動提陶,甚至完全沒有需要對整個系統(tǒng)進行停機烫沙。
剛下線 Google+,Mandy 又來提需求說最近合并了另一家銀行隙笆,客戶很多使用 Whatsapp锌蓄。二話不說,Jonnathan 直接上了一個新的模塊來處理 Whatsapp 撑柔,如下圖瘸爽。
又過了一段時間,這一次是他自己要對系統(tǒng)做調(diào)整了乏冀,原來 Snapchat 最近大火蝶糯,他部署的系統(tǒng)頻受壓力,性能下降辆沦。為了解決這個問題,Jonnathan 果斷增加了額外 2 臺容器來同時支撐 Snapchat 信息的采集和處理识虚。?
感謝微服務架構肢扯,Jonnathan 在一系列的產(chǎn)品需求變化以及系統(tǒng)擴容需求下,可以從容應付担锤。要實現(xiàn)微服務架構蔚晨,需要你銘記以下幾個微服務架構的應用設計原則。
解耦
在微服務架構中肛循,應用程序被分解為小型的獨立服務铭腕。服務通常專注于特定的離散目標或功能,并沿著業(yè)務邊界解耦多糠。按業(yè)務界限分離服務可讓團隊專注于正確的目標累舷,并確保服務之間的自主性。
? ? ? 每項服務都是獨立開發(fā)夹孔,測試和部署的被盈,服務通常是作為獨立的進程或軟件容器分開的析孽,通過網(wǎng)絡和商定的 API 進行通信,盡管在某些情況下只怎,網(wǎng)絡可能在本地袜瞬。通常部署相同微服務的多個實例,從而提供冗余和可擴展性身堡。
輕量級 API
? ? ? 微服務之間的通信要使用輕量級 API邓尤,如 HTTP RESTful API。這樣可以使得服務對 API 通信方案的依賴減到最小贴谎。
? ? ? 復雜的通信處理要在服務端進行裁赠,而不是像 ESB 或者 Data Pipeline 處理總線那樣在數(shù)據(jù)傳輸過程中引入非常多的邏輯,導致微服務模塊緊緊的綁定在這個數(shù)據(jù)管道上赴精。
持續(xù)發(fā)布
微服務架構帶來的一個非常顯著的負面性就是眾多實例的測試發(fā)布及管理佩捞。傳統(tǒng)應用雖然開發(fā)復雜,但是部署和運維相對比較集中蕾哟,一臺數(shù)據(jù)庫一忱,2-4 個應用服務器就差不多了。但是微服務架構下單獨服務的數(shù)量輕則 10-20谭确,多則上百個帘营,所以微服務架構一般需要配套的 CI/CD 方法來支撐。
數(shù)據(jù)與治理
? ? ? 數(shù)據(jù)的管理在微服務架構下也是和傳統(tǒng)單體有很大的不同考量逐哈。大部分時候我們希望數(shù)據(jù)就和服務一樣芬迄,要有充分的獨立性,可以和某個服務一起部署昂秃,一起擴展禀梳,或者一起重構。
這通常意味著我們可能要在一個微服務架構應用內(nèi)使用多個數(shù)據(jù)庫實例肠骆。但是同樣需要考慮到數(shù)據(jù)分布在多實例之間以后算途,往往還需要一些冗余,以及如何保持這些數(shù)據(jù)在這些系統(tǒng)中的一致性等問題蚀腿。下面我們就著重來討論微服務架構下的數(shù)據(jù)設計的一些考量因素嘴瓤。
微服務架構下的數(shù)據(jù)設計
? ? ? 從來沒有一個 one-size-fits-all 的架構,所以在微服務架構下面莉钙,我們需要了解的廓脆,一樣是幾個關鍵的架構考量點。然后針對自己的實際應用磁玉,選擇哪些考量點是更加重要的停忿。
這篇文章的目的,主要就是跟大家來討論從哪幾個角度著手蜀涨,來設計一個符合微服務架構原則的數(shù)據(jù)架構瞎嬉。比如說蝎毡,我們可以從一系列的問題來開始這個討論。
這么多微服務之間氧枣,我是否可以用一個數(shù)據(jù)庫沐兵,還是多個數(shù)據(jù)庫來支持多個微服務?
如果是多個數(shù)據(jù)庫便监,我是否為每一個微服務挑選一個最合適的數(shù)據(jù)庫扎谎,還是選擇同一種類型的數(shù)據(jù)庫?
我如何在微服務架構下擴展我的數(shù)據(jù)庫烧董?
當一個我依賴的服務需要修改數(shù)據(jù)庫 Schema 的時候毁靶,是否會影響到我?
當微服務應用不斷衍變的時候逊移,我的數(shù)據(jù)庫是否可以快速的響應應用需求變化预吆?以上這些就是我們在微服務數(shù)據(jù)架構時候要關注的地方。
一庫一服還是一庫多服
? ? ? 無論是單體應用胳泉,還是微服務應用拐叉,有一點是肯定的:應用的各個模塊之間都需要進行較為頻繁的通信,通過一起協(xié)同合作扇商,來實現(xiàn)應用的整體價值凤瘦。
? ? ? 在單體應用中,這種通信是通過方法調(diào)用來完成的案铺。在微服務中蔬芥,則通過 API 調(diào)用來完成。這些模塊或者服務間調(diào)用控汉,大部分時候是為了共享數(shù)據(jù)笔诵。
共享數(shù)據(jù)最賤的方式當然就是采用一種共享數(shù)據(jù)庫的模式,也就是單體應用常用的方式暇番。應用可以有多個系統(tǒng)模塊嗤放,但一般都是只有一個數(shù)據(jù)庫。如下圖左邊壁酬,3 個微服務模塊,后面共享一個數(shù)據(jù)庫恨课,簡稱一庫多服務舆乔。
? ? ? 這種架構模式通常會被認為是微服務架構下的反范式,它的問題在于:
單點故障:一個數(shù)據(jù)庫倒下剂公,整批服務全部停止希俩。何來的服務獨立性?
數(shù)據(jù)在同一個地方纲辽,會給貪圖方便的開發(fā)或者 DBA 工程師編寫很多數(shù)據(jù)間高度依賴的程序或者工具颜武。
無法針對某一個服務進行精準優(yōu)化或擴展璃搜,如上文所講的 Snapchat 的例子。
所以一般推薦的做法鳞上,是為每一個微服務準備一個單獨的數(shù)據(jù)庫这吻,也即一庫一服(Database per Service)模式。如上圖右側所示篙议。這種模式更加適合微服務架構唾糯,它滿足每一個服務是獨立開發(fā)、獨立部署鬼贱、獨立擴展的特性移怯。
當需要對一個服務進行升級或者數(shù)據(jù)架構改動的時候,不會影響到其他的服務这难。需要對某個服務進行擴展的時候舟误,也可以手術式的對某一個服務進行局部擴容。另外姻乓,如果某些服務對數(shù)據(jù)庫有特殊的需求嵌溢,這種模式也為下文所講的混合持久化(Polyglot Persistence)提供了可能性。
混合持久化 vs 多模數(shù)據(jù)庫
混合持久化在大型互聯(lián)網(wǎng)公司是一個比較風行的模式糖权。它秉承的原則就是為特別的任務提供最好的工具堵腹。比如說,如果我希望提供一個高并發(fā)低延遲的共享用戶會話方案(Shared Session Storage)星澳, Redis 可能是一個非常理想的選擇疚顷。
如果我是在實現(xiàn)一個產(chǎn)品目錄,涉及到大量不定結構的商品數(shù)據(jù)及屬性的建模管理禁偎,我可能會采用模式靈活腿堤,動態(tài) Schema 的 MongoDB 來作為我的數(shù)據(jù)庫解決方案。如果我希望支持非常強大的全文搜索如暖,ElasticSearch 則是行業(yè)中的佼佼者笆檀。
? ? ? 微服務的功能分塊獨立部署為這種架構模式提供了非常好的基礎,如上圖左側所示就是個典型的混合持久化的案例:
混合持久化:Polyglot Persistence
多模數(shù)據(jù)庫:Multi- model Database
當然盒至,有句話說的是架構師的工作就是每天做不斷的取舍(Trade Off)酗洒,因為選擇往往是讓人很糾結〖纤欤混合持久化的優(yōu)勢很明顯樱衷,可以讓每個單獨的服務使用到最佳的工具和技術。
? ? ? 但是它的弊端也是不容忽視:部署酒唉、監(jiān)控矩桂、備份、升級等數(shù)據(jù)庫管理工作從來都是一件困難但是重要的任務痪伦。引入多個不同的數(shù)據(jù)庫侄榴,也意味著對系統(tǒng)管理維護的復雜度和成本提高了很多雹锣。
? ? ? 這種情況下可能需要比較有資源的公司或者團隊才可以使用。這也解釋了這個模式為何在大型互聯(lián)網(wǎng)公司得到較多的采用與推廣癞蚕。
針對于其他小型規(guī)模的用戶蕊爵,或者是缺乏足夠掌握各種新型技術人才的公司來說,另一種更為可行的模式可能是多模數(shù)據(jù)庫(Multi-model)涣达。如上圖右側所示在辆,多模數(shù)據(jù)庫的特征是:
依然是一庫一服務(為一個服務部署一個單獨的數(shù)據(jù)庫)。
但是使用的是同一種類型度苔,支持多種場景的數(shù)據(jù)庫匆篓,如 NoSQL 中間為功能最全面的 MongoDB。
雖然是多實例寇窑,但是只需維護一種類型的數(shù)據(jù)庫鸦概,管理上和人員配備上都較為簡單。
? ? ? 如果你在開發(fā)的應用是一款企業(yè)級產(chǎn)品甩骏,會交付到客戶環(huán)境部署安裝窗市,則運維管理的簡單性將在技術選型中占據(jù)非常重要的一個比重,無疑這種情況下多模數(shù)據(jù)庫更加適用饮笛。
微服務擴展你的數(shù)據(jù)
? ? ? 微服務架構的一大裨益是其靈活的擴展性咨察。以上面的 Snapchat 為例,如果需要采集或處理的數(shù)據(jù)量快速增長福青,在我們增加應用服務實例的同時摄狱,支撐數(shù)據(jù)存儲的模塊也要相應擴充。
? ? ? AFK Partners 在他們的 Scale Cube 一文里對性能擴展提出了這樣的觀點无午,要設計一個真正意義上的可擴展系統(tǒng)媒役,我們必須考慮3個維度,如上圖所示:
X 軸宪迟,系統(tǒng)復制(橫向擴展)
Y 軸酣衷,非重疊功能的拆分(微服務)
Z 軸,數(shù)據(jù)的分區(qū)(Sharding)
一個好的數(shù)據(jù)架構次泽,在微服務體系內(nèi)穿仪,應該具有同樣的可擴展、易擴展性質意荤,從而不給微服務架構拖后腿牡借。關于數(shù)據(jù)分區(qū)擴展有兩種做法:
應用數(shù)據(jù)分區(qū)
數(shù)據(jù)庫分區(qū)
應用數(shù)據(jù)分區(qū),顧名思義袭异,就是在應用端對數(shù)據(jù)的存儲進行分區(qū)管理。比如說炬藤,一個社交應用可以按國家或地區(qū)為界把用戶的數(shù)據(jù)分發(fā)到不同數(shù)據(jù)庫實例里面御铃。這樣的話每個數(shù)據(jù)庫實例只需要存儲一部分數(shù)據(jù)碴里,從而實現(xiàn)海量的數(shù)據(jù)管理能力。
數(shù)據(jù)庫分區(qū)上真,就是由數(shù)據(jù)庫的路由節(jié)點來完成數(shù)據(jù)分區(qū)的任務咬腋。數(shù)據(jù)庫分區(qū)的優(yōu)勢是顯然的,它對應用透明睡互、擴展快速根竿、無須下線等。如果你的應用有潛在擴充的需求就珠,選擇一個能夠自動擴展的分布式數(shù)據(jù)庫是一個比較明智的選擇寇壳。
動態(tài)模式支持及快速開發(fā)能力
? ? ? 這是一個很多架構師可能會忽略,但是非常重要的關注點妻怎。我們在迭代式開發(fā) DevOps 微服務上的很多努力壳炎,都是為了快速開發(fā),快速上線逼侦,以及快速響應變化的需求匿辩。
? ? ? 從數(shù)據(jù)架構師的角度來看,如何不成為在這個快速開發(fā)方法模式中的一個瓶頸榛丢,有一個很重要的環(huán)節(jié)就是是否有一個能夠及時響應變化的數(shù)據(jù)模型铲球。
? ? ? 傳統(tǒng)的數(shù)據(jù)庫都是強模式,需要對 Schema 進行清晰定義, 在需求修改導致模型修改的時候需要對數(shù)據(jù)庫進行模式升級晰赞,是一個需要下線稼病、耗時并且是高成本的運維操作。
? ? ? 在新一代的 NoSQL 數(shù)據(jù)庫產(chǎn)生之前宾肺,我們并不需要考慮這個問題溯饵,但是以 MongoDB、Cassandra 等為代表的 NoSQL 代表的是靈活建模锨用。
動態(tài)支持模式變化的特征使得它們成為敏捷開發(fā)和微服務體系內(nèi)一個有力的競爭者丰刊,在選型的時候也是一個重要的考量因素之一。我們說一庫一服的架構使得對一個服務的數(shù)據(jù)庫模式修改不會影響到其他服務增拥。
? ? ? 但是如果使用一個動態(tài)模式(有時候有人會說無模式)的數(shù)據(jù)庫啄巧,則在該服務本身模式修改的時候也可以最小化運維成本。
一個適合微服務架構的數(shù)據(jù)庫
? ? ? 紅杉資本的合伙人 Matt Miller 是公認的微服務技術領域專家掌栅。他廣被傳播的“微服務生態(tài)圖”詳盡的列出了微服務架構的相關技術棧秩仆。在這里他推薦了 MongoDB 作為主要的數(shù)據(jù)管理方案。
MongoDB 是一個分布式文檔型數(shù)據(jù)庫猾封,它有以下特性使它非常適合于微服務架構澄耍,其主要特點包括:多模數(shù)據(jù)庫(Multi-model)、原生 JSON 數(shù)據(jù)結構API、動態(tài)模式齐莲、無模式(Dynamic schema)痢站、數(shù)據(jù)變化流(Change Stream)、橫向擴展能力(Sharding)选酗。
多模數(shù)據(jù)庫
? ? ? MongoDB 從 3.4 版本起在多模數(shù)據(jù)庫場景上提供了不少功能模塊阵难,比如說,使用聚合框架∶⑻睿現(xiàn)在開發(fā)者可以使用:
$graphLookup 來實現(xiàn)類似于圖數(shù)據(jù)庫的查詢呜叫。
$facet 來實現(xiàn)分面搜索。
內(nèi)存引擎功能殿衰,用于支持類似于 Redis 的高速緩存朱庆。
全文檢索,用于實現(xiàn)搜索類型場景播玖。
動態(tài)模式
? ? ? 這一點一直是 MongoDB 獲得開發(fā)者青睞的主要原因之一椎工。MongoDB 無須顯式的定義數(shù)據(jù)模式即可讓你開始往數(shù)據(jù)庫寫入。
當數(shù)據(jù)模型有變化時候蜀踏,比如說在迭代式開發(fā)中非常常見的就是增加一些字段维蒙,MongoDB 數(shù)據(jù)庫不需要對其進行修改 Schema 操作,而是可以直接在同一個集合(表)里直接寫入新版本的文檔果覆。這個對于需要實現(xiàn)快速迭代颅痊,快速交付的微服務應用開發(fā)是一個非常重要的特性。
數(shù)據(jù)變化流
微服務架構中由于其分布特性局待,傳統(tǒng)的強事務機制不再適用斑响。數(shù)據(jù)的一致性一般需要通過一些基于 Event Sourcing 或者事件驅動模型的解決方案。Mongo DB 3.6 版本推出的數(shù)據(jù)更改流钳榨,可以用來實現(xiàn)一個類似于 Kafak 一樣的 Message Queue舰罚,為各個微服務間的數(shù)據(jù)協(xié)調(diào)提供一個簡單易用的線程方案。
橫向擴展能力
? ? ? MongoDB 一向以其強大的橫向擴展能力著稱薛耻。不少 MongoDB 用戶遷移的主要原因就是使用 MongoDB 的 Sharding 技術可以突破關系型數(shù)據(jù)庫在數(shù)據(jù)量和性能上的瓶頸营罢。
? ? ? MongoDB 的 Sharding 有幾個特征使得其非常適合微服務架構使用:
彈性擴展:可以擴容也可以縮容。
無縫擴展:無須停機饼齿,就可在線擴容饲漾。
自動均衡:無須應用參與即可實現(xiàn)數(shù)據(jù)的自動均衡,完全透明缕溉。一個基于 MongoDB 的微服務參考架構圖考传。
歡迎工作一到五年的Java工程師朋友們加入Java程序員開發(fā): 854393687
群內(nèi)提供免費的Java架構學習資料(里面有高可用、高并發(fā)证鸥、高性能及分布式僚楞、Jvm性能調(diào)優(yōu)勤晚、Spring源碼,MyBatis镜硕,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點的架構資料)合理利用自己每一分每一秒的時間來學習提升自己运翼,不要再用"沒有時間“來掩飾自己思想上的懶惰!趁年輕兴枯,使勁拼,給未來的自己一個交代矩欠!