歡迎光臨
每天分享高質量文章

一文詳解微服務架構的資料設計

作者:唐建法

編輯:陶家龍、孫淑娟

出處:Mongoing中文社群

      微服務是一個軟體架構樣式,對微服務的討論大多集中在容器或其他技術是否能很好的實施微服務這些方面。

      本文將從以下幾個角度來和大家分享在微服務架構下進行資料設計需要關註的地方,旨在幫助大家在構建微服務架構時,提供一個資料方面的視角:

  • 什麼是微服務

  • 微服務的優勢及架構特點

  • 微服務架構下的資料設計

  • 一個適合微服務架構的資料庫

什麼是微服務

      按照 Martin Fowler 的定義,微服務是一個軟體架構樣式,透過開發一系列的小型服務的方式來實現一個應用。每一個這樣的小服務通常都是執行在自己的行程裡面,並且透過輕量級的HTTP API 方式進行通訊。


      這些服務通常會以業務模組為界限,能夠被單獨開發部署,往往都會用自動化的部署工具來進行產品的釋出。透過使用微服務方法,大公司可以更快推出新產品和服務,使得開發團隊與業務標的保持一致。

微服務的優勢

      微服務方法體現出許多優勢,包括更快的上線時間、靈活性、彈性、一致性以及相對更低的成本。


  • 更快的上線時間


      實施微服務架構可以使組織更快地將應用程式推向市場。對整體應用程式的更改(即使很小)需要重新部署整個應用程式堆疊,從而引入風險和複雜性。


      相反,服務的更新可以立即提交、測試和部署,對個別服務的更改不會影響系統的其他部分。


  • 更好的靈活性和可擴充套件性


      微服務方法在擴充套件應用程式時也提供了靈活性。單片應用程式要求整個系統(及其所有功能)同時擴充套件。


      使用微服務,只需要縮放需要額外效能的元件或功能。可以透過部署更多微服務實體來擴充套件服務範圍,從而實現更有效的容量規劃並降低軟體許可成本,從而降低總體擁有成本。


  • 彈性


      使用單體應用程式時,元件的故障可能會危及整個應用程式。在微服務中,每項服務都是隔離的,以防止級聯失敗導致整個系統崩潰。如果單個微服務的所有實體均失敗,則整體服務可能會降級,但其他元件仍可提供有價值的服務。


  • 更容易的規模化


      微服務使技術團隊能夠與組織需求保持一致,並且可以調整團隊的大小以匹配所需的任務。通常,微服務團隊規模較小,但是跨部門(如一般涵蓋Ops、Dev、QA),並專註於整個應用程式的單個元件。


      透過提供對個人服務的所有權,而不是功能區域,微服務還可以打破團隊之間的孤島,並改善協作。這種方法對於分散式和遠端團隊尤其強大。 例如,不同地點的團隊可以獨立釋出和部署功能。

微服務的技術特點

      讓我們通過一個例子來瞭解微服務架構的技術特點聯邦銀行的架構師 Jonnathan 非常不喜歡他的產品經理 Mandy,因為他覺得 Mandy 永遠有無窮無盡的想法要實現,搞得他成天就在不斷地修改程式碼。


      但是 Mandy 是老闆的紅人,而且使用者對產品的反響也不錯,所以很多時候他只能默默的服從。這一天 Mandy 又成功的說服了老闆要在他們的客戶體驗提升專案中增加輿情分析和 AI 客戶服務模組,希望透過對社交媒體上有關聯邦銀行的所有評論進行實時的監控和分析來及時發現聯邦銀行的產品反饋或者使用者體驗問題。


      Jonnathan已經預感到了這樣前所未有的應用場景,會有太多的未知和太多的改變,於是這次決定嘗試使用 Microservices 來構建這個應用。這個是 Jonnathan 設計的架構,系統要求對客戶的社交賬號,如 Facebook、Twitter、Google+ 及 Snapchat 公開的資訊及評論進行收集,併在某些合適的時候使用 AI 技術直接和使用者透過社交工具進行互動。


      在上圖這個架構裡面,Jonnathan 把4個不同社交媒體的資料採集和互動用 4 個獨立的模組進行實現。並用一個 Feed Merge 服務,一個 Aggregate Service 把 4 個類似功能的微服務模組的資料和功能進行整合,提供給分析平臺使用。


      這裡面每一個服務按照微服務的架構,每一個都是單獨部署,在一個獨立的容器內執行,並使用自己的一個資料庫。


      果不其然,系統上線一段時間後,Mandy 說 Google+ 上面幾乎沒有什麼活動,不值得繼續維護這樣的一套系統。Jonnathan 這次毫無抱怨,直接把負責 Google+ 的容器停了,沒有需要任何程式碼改動,甚至完全沒有需要對整個系統進行停機。

      剛下線 Google+,Mandy 又來提需求說最近合併了另一家銀行,客戶很多使用 Whatsapp。二話不說,Jonnathan 直接上了一個新的模組來處理 Whatsapp ,如下圖。


 

      又過了一段時間,這一次是他自己要對系統做調整了,原來 Snapchat 最近大火,他部署的系統頻受壓力,效能下降。為瞭解決這個問題,Jonnathan 果斷增加了額外 2 臺容器來同時支撐 Snapchat 資訊的採集和處理。 


      感謝微服務架構,Jonnathan 在一系列的產品需求變化以及系統擴容需求下,可以從容應付。要實現微服務架構,需要你銘記以下幾個微服務架構的應用設計原則。


解耦


      在微服務架構中,應用程式被分解為小型的獨立服務。服務通常專註於特定的離散標的或功能,並沿著業務邊界解耦。按業務界限分離服務可讓團隊專註於正確的標的,並確保服務之間的自主性。


      每項服務都是獨立開發,測試和部署的,服務通常是作為獨立的行程或軟體容器分開的,透過網路和商定的 API 進行通訊,儘管在某些情況下,網路可能在本地。通常部署相同微服務的多個實體,從而提供冗餘和可擴充套件性。


輕量級 API


      微服務之間的通訊要使用輕量級 API,如 HTTP RESTful API。這樣可以使得服務對 API 通訊方案的依賴減到最小。

      複雜的通訊處理要在服務端進行,而不是像 ESB 或者 Data Pipeline 處理匯流排那樣在資料傳輸過程中引入非常多的邏輯,導致微服務模組緊緊的系結在這個資料管道上。


持續釋出


      微服務架構帶來的一個非常顯著的負面性就是眾多實體的測試釋出及管理。傳統應用雖然開發複雜,但是部署和運維相對比較集中,一臺資料庫,2-4 個應用伺服器就差不多了。但是微服務架構下單獨服務的數量輕則 10-20,多則上百個,所以微服務架構一般需要配套的 CI/CD 方法來支撐。


資料與治理


      資料的管理在微服務架構下也是和傳統單體有很大的不同考量。大部分時候我們希望資料就和服務一樣,要有充分的獨立性,可以和某個服務一起部署,一起擴充套件,或者一起重構。


      這通常意味著我們可能要在一個微服務架構應用內使用多個資料庫實體。但是同樣需要考慮到資料分佈在多實體之間以後,往往還需要一些冗餘,以及如何保持這些資料在這些系統中的一致性等問題。下麵我們就著重來討論微服務架構下的資料設計的一些考量因素。

微服務架構下的資料設計


      從來沒有一個 one-size-fits-all 的架構,所以在微服務架構下麵,我們需要瞭解的,一樣是幾個關鍵的架構考量點。然後針對自己的實際應用,選擇哪些考量點是更加重要的。


      這篇文章的目的,主要就是跟大家來討論從哪幾個角度著手,來設計一個符合微服務架構原則的資料架構。比如說,我們可以從一系列的問題來開始這個討論。


  • 這麼多微服務之間,我是否可以用一個資料庫,還是多個資料庫來支援多個微服務?

  • 如果是多個資料庫,我是否為每一個微服務挑選一個最合適的資料庫,還是選擇同一種型別的資料庫?

  • 我如何在微服務架構下擴充套件我的資料庫?

  • 當一個我依賴的服務需要修改資料庫 Schema 的時候,是否會影響到我?

  • 當微服務應用不斷衍變的時候,我的資料庫是否可以快速的響應應用需求變化?以上這些就是我們在微服務資料架構時候要關註的地方。


一庫一服還是一庫多服


      無論是單體應用,還是微服務應用,有一點是肯定的:應用的各個模組之間都需要進行較為頻繁的通訊,透過一起協同合作,來實現應用的整體價值。


      在單體應用中,這種通訊是透過方法呼叫來完成的。在微服務中,則透過 API 呼叫來完成。這些模組或者服務間呼叫,大部分時候是為了共享資料。


      共享資料最賤的方式當然就是採用一種共享資料庫的樣式,也就是單體應用常用的方式。應用可以有多個系統模組,但一般都是隻有一個資料庫。如下圖左邊,3 個微服務模組,後面共享一個資料庫,簡稱一庫多服務。


      這種架構樣式通常會被認為是微服務架構下的反正規化,它的問題在於:

  • 單點故障:一個資料庫倒下,整批服務全部停止。何來的服務獨立性?

  • 資料在同一個地方,會給貪圖方便的開發或者 DBA 工程師編寫很多資料間高度依賴的程式或者工具。

  • 無法針對某一個服務進行精準最佳化或擴充套件,如上文所講的 Snapchat 的例子。


      所以一般推薦的做法,是為每一個微服務準備一個單獨的資料庫,也即一庫一服(Database per Service)樣式。如上圖右側所示。這種樣式更加適合微服務架構,它滿足每一個服務是獨立開發、獨立部署、獨立擴充套件的特性。


      當需要對一個服務進行升級或者資料架構改動的時候,不會影響到其他的服務。需要對某個服務進行擴充套件的時候,也可以手術式的對某一個服務進行區域性擴容。另外,如果某些服務對資料庫有特殊的需求,這種樣式也為下文所講的混合持久化(Polyglot Persistence)提供了可能性。

混合持久化 vs 多模資料庫


      混合持久化在大型網際網路公司是一個比較風行的樣式。它秉承的原則就是為特別的任務提供最好的工具。比如說,如果我希望提供一個高併發低延遲的共享使用者會話方案(Shared Session Storage), Redis 可能是一個非常理想的選擇。


      如果我是在實現一個產品目錄,涉及到大量不定結構的商品資料及屬性的建模管理,我可能會採用樣式靈活,動態 Schema 的 MongoDB 來作為我的資料庫解決方案。如果我希望支援非常強大的全文搜尋,ElasticSearch 則是行業中的佼佼者。


      微服務的功能分塊獨立部署為這種架構樣式提供了非常好的基礎,如上圖左側所示就是個典型的混合持久化的案例:

  • 混合持久化:Polyglot Persistence

  • 多模資料庫:Multi- model Database


      當然,有句話說的是架構師的工作就是每天做不斷的取捨(Trade Off),因為選擇往往是讓人很糾結。混合持久化的優勢很明顯,可以讓每個單獨的服務使用到最佳的工具和技術。


      但是它的弊端也是不容忽視:部署、監控、備份、升級等資料庫管理工作從來都是一件困難但是重要的任務。引入多個不同的資料庫,也意味著對系統管理維護的複雜度和成本提高了很多。


      這種情況下可能需要比較有資源的公司或者團隊才可以使用。這也解釋了這個樣式為何在大型網際網路公司得到較多的採用與推廣。


      針對於其他小型規模的使用者,或者是缺乏足夠掌握各種新型技術人才的公司來說,另一種更為可行的樣式可能是多模資料庫(Multi-model)。如上圖右側所示,多模資料庫的特徵是:


  • 依然是一庫一服務(為一個服務部署一個單獨的資料庫)。

  • 但是使用的是同一種型別,支援多種場景的資料庫,如 NoSQL 中間為功能最全面的 MongoDB。

  • 雖然是多實體,但是隻需維護一種型別的資料庫,管理上和人員配備上都較為簡單。


      如果你在開發的應用是一款企業級產品,會交付到客戶環境部署安裝,則運維管理的簡單性將在技術選型中佔據非常重要的一個比重,無疑這種情況下多模資料庫更加適用。


微服務擴充套件你的資料


      微服務架構的一大裨益是其靈活的擴充套件性。以上面的 Snapchat 為例,如果需要採集或處理的資料量快速增長,在我們增加應用服務實體的同時,支撐資料儲存的模組也要相應擴充。

      AFK Partners 在他們的 Scale Cube 一文裡對效能擴充套件提出了這樣的觀點,要設計一個真正意義上的可擴充套件系統,我們必須考慮3個維度,如上圖所示:

  • X 軸,系統複製(橫向擴充套件)

  • Y 軸,非重疊功能的拆分(微服務)

  • Z 軸,資料的分割槽(Sharding)


      一個好的資料架構,在微服務體系內,應該具有同樣的可擴充套件、易擴充套件性質,從而不給微服務架構拖後腿。關於資料分割槽擴充套件有兩種做法:


  • 應用資料分割槽

  • 資料庫分割槽


      應用資料分割槽,顧名思義,就是在應用端對資料的儲存進行分割槽管理。比如說,一個社交應用可以按國家或地區為界把使用者的資料分發到不同資料庫實體裡面。這樣的話每個資料庫實體只需要儲存一部分資料,從而實現海量的資料管理能力。


      資料庫分割槽,就是由資料庫的路由節點來完成資料分割槽的任務。資料庫分割槽的優勢是顯然的,它對應用透明、擴充套件快速、無須下線等。如果你的應用有潛在擴充的需求,選擇一個能夠自動擴充套件的分散式資料庫是一個比較明智的選擇。


動態樣式支援及快速開發能力


      這是一個很多架構師可能會忽略,但是非常重要的關註點。我們在迭代式開發 DevOps 微服務上的很多努力,都是為了快速開發,快速上線,以及快速響應變化的需求。


      從資料架構師的角度來看,如何不成為在這個快速開發方法樣式中的一個瓶頸,有一個很重要的環節就是是否有一個能夠及時響應變化的資料模型。


      傳統的資料庫都是強樣式,需要對 Schema 進行清晰定義, 在需求修改導致模型修改的時候需要對資料庫進行樣式升級,是一個需要下線、耗時並且是高成本的運維操作。

      在新一代的 NoSQL 資料庫產生之前,我們並不需要考慮這個問題,但是以 MongoDB、Cassandra 等為代表的 NoSQL 代表的是靈活建模。


      動態支援樣式變化的特徵使得它們成為敏捷開發和微服務體系內一個有力的競爭者,在選型的時候也是一個重要的考量因素之一。我們說一庫一服的架構使得對一個服務的資料庫樣式修改不會影響到其他服務。


      但是如果使用一個動態樣式(有時候有人會說無樣式)的資料庫,則在該服務本身樣式修改的時候也可以最小化運維成本。

一個適合微服務架構的資料庫

      紅杉資本的合夥人 Matt Miller 是公認的微服務技術領域專家。他廣被傳播的“微服務生態圖”詳盡的列出了微服務架構的相關技術棧。在這裡他推薦了 MongoDB 作為主要的資料管理方案。


      MongoDB 是一個分散式檔案型資料庫,它有以下特性使它非常適合於微服務架構,其主要特點包括: 多模資料庫(Multi-model)、原生 JSON 資料結構API、動態樣式、無樣式(Dynamic schema)、資料變化流(Change Stream)、橫向擴充套件能力(Sharding)。


多模資料庫


      MongoDB 從 3.4 版本起在多模資料庫場景上提供了不少功能模組,比如說,使用聚合框架。現在開發者可以使用:

  • $graphLookup 來實現類似於圖資料庫的查詢。

  • $facet 來實現分面搜尋。

  • 記憶體引擎功能,用於支援類似於 Redis 的高速快取。

  • 全文檢索,用於實現搜尋型別場景。


動態樣式


      這一點一直是 MongoDB 獲得開發者青睞的主要原因之一。MongoDB 無須顯式的定義資料樣式即可讓你開始往資料庫寫入。


      當資料模型有變化時候,比如說在迭代式開發中非常常見的就是增加一些欄位,MongoDB 資料庫不需要對其進行修改 Schema 操作,而是可以直接在同一個集合(表)裡直接寫入新版本的檔案。這個對於需要實現快速迭代,快速交付的微服務應用開發是一個非常重要的特性。


資料變化流


      微服務架構中由於其分佈特性,傳統的強事務機制不再適用。資料的一致性一般需要透過一些基於 Event Sourcing 或者事件驅動模型的解決方案。Mongo DB 3.6 版本推出的資料更改流,可以用來實現一個類似於 Kafak 一樣的 Message Queue,為各個微服務間的資料協調提供一個簡單易用的執行緒方案。


橫向擴充套件能力


      MongoDB 一向以其強大的橫向擴充套件能力著稱。不少 MongoDB 使用者遷移的主要原因就是使用 MongoDB 的 Sharding 技術可以突破關係型資料庫在資料量和效能上的瓶頸。

      MongoDB 的 Sharding 有幾個特徵使得其非常適合微服務架構使用:

  • 彈性擴充套件:可以擴容也可以縮容。

  • 無縫擴充套件:無須停機,就可線上擴容。

  • 自動均衡:無須應用參與即可實現資料的自動均衡,完全透明。一個基於 MongoDB 的微服務參考架構圖。


熱文推薦:


      關於容器和Docker詳細分析,請透過“原文連結”參閱作者總結的<容器技術架構、網路和生態詳解>電子書。



溫馨提示:
請搜尋“ICT_Architect”“掃一掃”二維碼關註公眾號,點選原文連結獲閱讀原文瞭解更多

求知若渴, 虛心若愚

贊(0)

分享創造快樂