Mysql保存是事件驅動嗎_【CHRIS RICHARDSON 微服務系列】事件驅動的數據管理-5

編者的話 |本文來自 Nginx 官方博客,是「Chris Richardson 微服務」系列的第五篇文章。第一篇文章介紹了微服務架構模式,并且討論了使用微服務的優缺點;第二和第三篇描述了微服務架構模塊間通訊的不同方面;第四篇研究了服務發現中的問題。本篇研究微服務架構帶來的分布式數據管理問題。

作者介紹:Chris Richardson,是世界著名的軟件大師,經典技術著作《POJOS IN ACTION》一書的作者,也是 cloudfoundry.com 最初的創始人,Chris Richardson 與 Martin Fowler、Sam Newman、Adrian Cockcroft 等并稱為世界十大軟件架構師。

Chris Richardson 微服務系列全 7 篇:

微服務以及分布式數據管理中存在的問題

單體應用通常使用單個關系型數據庫,由此帶來的好處在于應用能夠使用 ACID 事務,后者提供了重要的操作特性:

原子化:原子粒度的更改

一致性:數據庫的狀態始終保持一致

隔離:并發執行的事務顯示為串行執行

持久:事務一旦提交就不會被撤銷

如此,應用能夠簡單地開始事務、更改(插入、更新和刪除)多行、以及提交事務。

使用關系型數據庫的另一大好處是它支持 SQL。SQL 是一門豐富、可聲明的和標準化的查詢預約。用戶能夠輕松通過查詢將多個表中的數據組合起來,然后 RDBMS 查詢調度器決定執行查詢的最優方法。用戶不必關心底層細節,比如如何訪問數據庫。此外,由于所有的應用數據在一個數據庫中,很容易查詢。

然而,微服務架構中的數據訪問變得復雜許多。每個微服務擁有的數據專門用于該微服務,僅通過其 API 訪問。這種數據封裝保證了微服務松散耦合,并且可以獨立更新。但如果多個服務訪問相同數據,架構更新會耗費時間、也需要所有服務的協調更新。

更糟糕的是,不同的微服務通常使用不同類型的數據庫。現代應用存儲和處理各種類型的數據,而關系型數據庫并非總是好選擇。對于一些使用場景,特定的 NoSQL 數據庫能提供更方便的數據模型、更好的性能和可擴展性。譬如,服務使用 Elasticsearch 這樣的文本搜索引擎來存儲和查詢文本;同樣地,存儲社交圖譜數據的服務可能需要使用 Neo4j 這樣的圖譜數據庫。因此,基于微服務的應用通常會混合使用 SQL 和 NoSQL 數據庫,即多語言留存(polyglot persistence approach)。

分區的、多語言留存的架構對于數據存儲有很多好處,包括服務的松耦合、更好的性能和可擴展性。然而,它也確實給分布式數據管理帶來了挑戰。

第一個挑戰就是如何實現業務邏輯,保持多種服務的一致性。為了說明為何這是一個問題,我們以在線 B2B 商店為例。Customer Service(下文使用客戶服務)維護與用戶有關的信息,包括信用信息。Order Service(下文使用訂單服務)管理訂單,驗證新訂單沒有超出用戶的信用額度。在單體應用里,訂單服務可以簡單地使用 ACID 事務來核對提供的信用信息和創建訂單。

相反,在微服務架構中,如下圖所示,訂單表和客戶表為各自對應的服務私有。

e91e97adffdcb2e740531dc8ba93a974.png

訂單服務無法直接訪問客戶表,只能通過客戶服務提供的 API。訂購服務可能使用分布式事務,也被稱為兩步提交(2PC)。然而,2PC 通常不是現代應用的可行選項。CAP 定理需要用戶在可用性和 ACID 風格的一致性中二選一,通常可用性是更好的選擇。此外,許多現代技術,譬如大多數 NoSQL 數據庫并不支持 2PC。維護整個服務和數據庫中的數據一致性是至關重要的,因此我們需要另一種解決方案。

第二個挑戰就是如何實現檢索多個服務數據的查詢。假設應用需要顯示一位客戶和他的最近的訂單。如果訂單服務為檢索客戶訂單提供了 API,那么可以使用應用端獲取該數據。應用通過客戶服務檢索該客戶,通過訂單服務檢索該顧客的訂單。但是假如訂單服務只支持通過訂單主鍵查詢訂單(可能使用僅支持鍵值檢索的 NoSQL 數據庫),這種情況下,就沒有合適的方法來檢索所需數據。

事件驅動的架構

對于許多應用,解決方案就是事件驅動的架構。在這一架構里,當有顯著事件發生時,譬如更新業務實體,某個微服務會發布事件,其它微服務則訂閱這些事件。當某一微服務接收到事件就可以更新自己的業務實體,實現更多事件被發布。

用戶能夠使用事件來實現跨多個服務的業務邏輯。事務由一系列步驟組成,每一步都有一個微服務更新業務實體,然后發布觸發下一步的事件。下面的系列圖展示了如何使用事件驅動的方法在創建訂單時檢查可用信用。微服務通過消息代理來交換事件。

訂單服務創建狀態為 NEW 的訂單,并發布“訂單已創建”事件。

6113c3b12b0a50eabd522d77b8cfe6c4.png

客戶服務獲取“訂單已創建”事件,為此訂單保留信用,發布“信用保留”事件。

1d98a514435ae77dcc3d9770dcc84bca.png

訂單服務獲取“信用保留”事件,把訂單狀態修改為 OPEN。

2faeab94f25539fc585f0d875247413a.png

更為復雜的場景可能涉及更多的步驟,比如在核對客戶信用的同時預留庫存。

基于(a)每個服務自動更新數據庫和發布事件,以及(b)消息代理確保事件傳遞至少一次,用戶能夠跨多個服務完成業務邏輯。注意它們并非 ACID 業務。這種模式提供弱確定性,比如最終一致性。這種事務模型也被稱作 BASE 模型。

用戶也可以使用事件來維護不同微服務擁有的預連接數據的物化視圖。維護此視圖的服務訂閱相關事件,并更新視圖。例如,維護客戶訂單視圖的客戶訂單視圖更新服務會訂閱由客戶服務和訂單服務發布的事件。

5e5f4e034888494c864abad494c660cc.png

當客戶訂單查看更新服務收到客戶或者訂單事件,就會更新客戶訂單查看的數據存儲。用戶能夠使用類似 MongoDB 的文檔數據庫查看用戶訂單,并為每位客戶存儲一個文檔。用戶訂單預覽查詢服務通過客戶訂單預覽數據存儲,處理來自客戶和最近訂單的請求。

事件驅動的架構有優點也有缺點。它使得事務跨多個服務并提供最終一致性,也可以讓應用維護物化視圖。缺點之一在于,它的編程模型要比使用 ACID 事務的更加復雜。為了從應用級別的失效中恢復,還需要完成補償性事務,例如,如果信用檢查不成功則必須取消訂單。此外,由于臨時事務造成的改變顯而易見,因而應用必須處理不一致的數據。此外,如果應用從物化視圖中讀取的數據沒有更新時,也會遇到不一致的問題。此架構的另一缺點就是用戶必須檢測并忽略重復事件。

實現原子化

事件驅動的架構還存在以原子粒度更新數據庫并發布事件的問題。例如,訂單服務必須在訂單表中插入一行,然后發布“訂單已創建”事件。這兩個操作需要原子化實現。如果服務在更新數據庫之后、發布事件之前崩潰,系統變得不一致。確保原子化的標準做法是使用包含數據庫和消息代理的分布式事務。然而,基于以上描述的 CAP 理論,這并非我們所想。

使用本地事務發布事件

實現原子化的方法是使用多步驟進程來發布事件,該進程只包含本地事務。訣竅就是在存儲業務實體狀態的數據庫中,有一個事件表來充當消息隊列。應用啟動一個(本地)數據庫事務,更新業務實體的狀態,在事件表中插入一個事件,并提交該事務。獨立的應用線程或進程查詢事件表,將事件發不到消息代理,然后使用本地事務標注事件并發布。下圖展示了這一設計。

925b4e5e0fc640555ab7dc6964b35a61.png

訂單服務在訂單表中插入一行,然后在事件表中插入“訂單已創建”的事件。時間發布線程或進程在事件表中查詢未發布的事件并發布,然后更新事件表,將該事件標記為已發布。

這種方法優缺點兼具。優點之一是保證每個更新都有對應的事件發布,并且無需依賴 2PC。此外,應用發布業務級別的事件,消除了推斷事件的需要。這種方法也有缺點。由于開發者必須牢記發布事件,因此有很大可能出錯。此外這一方法對于某些使用 NoSQL 數據庫的應用是個挑戰,因為 NoSQL 本身交易和查詢能力有限。

通過此方法,應用使用本地事務來更新狀態和發布事件,排除了對 2PC 的需要。接下來,我們了解使用應用更新狀態實現原子化的方法。

挖掘數據庫事務日志

無需 2PC 實現原子化的另一種方式是由線程或者進程通過挖掘數據庫事務或提交日志來發布事件。應用更新數據庫,數據庫的事務日志記錄這些變更。事務日志挖掘線程或進程讀取這些日志,并把事件發布到消息代理。如下圖所示:

9b51ddd85b50eb5e40c3b741abcaab31.png

這一方法的范例是開源的 LinkedIn Databus 項目。Databus 挖掘 Oracle 事務日志并發布與之對應的事件。LinkedIn 使用 Databus 維持各種來源的數據存儲與記錄系統一致。

另一個范例則是 AWS DynamoDB 采用的流機制,AWS DynamoDB 是一個可管理的 NoSQL 數據庫。每個 DynamoDB 流包括 DynamoDB 表在過去 24 小時之內的時序變化,包括創建、更新和刪除操作。應用能夠讀取這些變更,將其作為事件發布。

事務日志挖掘具有多個優點。首先,它能保證無需使用 2PC 就能針對每個更新發布事件。其次,通過將日志發布于應用的業務邏輯分離,事務日志挖掘能夠簡化應用。事務日志挖掘也有缺點,主要缺點就是事務日志的格式與每個數據庫對應,甚至隨著數據庫版本而變化。此外,很難從底層事務日志更新記錄中逆向工程這些業務事件。

通過讓應用更新數據庫,事務日志挖掘消除了對 2PC 的需要。接下來我們會討論另一種方法——消除更新,只依賴事件。

使用事件源

通過采用一種截然不同的、以事件為中心的方法來留存業務實體,事件源無需 2PC 實現了原子化。不同于存儲實體的當前狀態,應用存儲狀態改變的事件序列。應用通過重播事件來重構實體的當前狀態。每當業務實體的狀態改變,新事件就被附加到事件列表。鑒于保存事件是一個單一的操作,本質上也是原子化的。

要了解事件源如何運行,可以以訂單實體為例。在傳統的方法中,每個訂單映射為訂單表的一行,例如一個 ORDERLINEITEM 表。使用事件源的時候,訂單服務以狀態更改事件的方式存儲訂單,包括已創建、已批準、已發貨、已取消等。每個事件都包含足夠的數據去重建訂單狀態。

e7a2d0baba1342ac3cd4a97a71075e4b.png

事件長期保存在事件數據庫,使用 API 添加和檢索實體的事件。事件存儲類似上文提及的消息代理,通過 API 讓服務訂閱事件,將所有事件傳達到所有感興趣的訂閱者。事件存儲是事件驅動的微服務架構的支柱。

事件源有不少優點。它解決了實施事件驅動的微服務架構時的一個關鍵問題,能夠只要狀態改變就可靠地發布事件。另外,它也解決了微服務架構中的數據一致性問題。由于儲存事件而不是域對象,它也避免了對象關系抗阻不匹配的問題(object?relational impedance mismatch problem)。事件源提供了 100% 可靠的業務實體變化的審計日志,使得獲取任何時間點的實體狀態成為可能。事件源的另一大優勢在于業務邏輯由松耦合的、事件交換的業務實體構成,便于從單體應用向微服務架構遷移。

事件源也有缺點。由于采用了不同或不熟悉的編程風格,會有學習曲線。事件存儲只直接支持通過主鍵查詢業務實體,用戶還需要使用 Command Query Responsibility Segregation (CQRS) 來完成查詢。因此,應用必須處理最終一致的數據。

總結

在微服務架構中,每個微服務都有其私有數據存儲,不同的微服務可能使用不同的 SQL 和 NoSQL 數據庫。這些數據庫架構帶來便利的同時,也給分布式數據管理帶來挑戰。第一個挑戰就是如何實現業務事務,保持多個服務的一致性。第二個挑戰就是如何從多個服務中檢索數據,實現查詢。

對于許多應用,解決方案就是使用事件驅動的架構。事件驅動的架構帶來的挑戰是如何原子化地更新狀態和發布事件。有幾個方法可以做到這一點,包括把數據庫用作消息隊列、事務日志挖掘和事件源。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/534917.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/534917.shtml
英文地址,請注明出處:http://en.pswp.cn/news/534917.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

chrome postman插件_收集了一些Chrome插件神器,助你快速成為老司機

剛開始開發項目的時候,我一直都在用火狐,因為它有一個fireBug插件,特別好用(目前已不支持),也不知道什么時候,就一直用起來Chrome瀏覽器了,可能是因為它有強大的插件作為后盾吧。開發了這么多年&#xff0c…

phpmyadmin 導出mysql,在phpmyadmin中導入/導出非常大的mysql數據庫

i have a db in phpmyadmin having 3000000 records. i want to export this to another pc. now when i export this only 200000 entries exported into .sql file and that is also not imported on the other pc.解決方案Answering this for anyone else who lands here. I…

python字符串是否包含某元素_Python實現判斷一個字符串是否包含子串的方法總結...

本文實例總結了Python實現判斷一個字符串是否包含子串的方法。分享給大家供大家參考,具體如下: 1.使用成員操作符 in >>> snihao,shijie >>> tnihao >>> result t in s >>> print result True 2.使用string模塊的f…

python怎么全選_有沒有一種方法可以在Python網頁上模擬“全選復制粘貼”?

我對Python相當陌生,我不知道selenium是什么,但是如果您能夠找到某種模式,您應該能夠執行您描述的內容。關鍵是找到一個模式。下面是幾個示例腳本,它們可能會讓您了解如何開始。在import urllib2from bs4 import BeautifulSoupf …

python當前時間怎么弄_python獲取當前時間

我有的時候寫程序要用到當前時間,我就想用python去取當前的時間,雖然不是很難,但是老是忘記,用一次丟一次, 為了能夠更好的記住,我今天特意寫下這篇文章,如果你覺的對你有用的話,可以…

window.open不重復打開同一個名稱的窗口_干貨滿滿|Ctrl鍵的正確打開方式

“ctrl”是鍵盤中一個常用的鍵,全名為"control",中文意為"控制",在計算機基礎中稱為“控制鍵”。那么你知道“ctrl”都能控制什么嗎?難道只知道 “ctrl”C 復制、“ctrl”V 粘貼 這些?&#xff1f…

java 按位_Java中的按位運算

一、位運算符簡介:1.按位與&。如果兩個整形數據 a、b 對應位都是1,則結果位才為1,否則為0,(int 最大值0x7fffffff ):1 int a 0x7fffffff;2 int b 12;3 int c 0;4 int aAndB a&b; //aAndB is 125 int aAndC a&c; …

jmeter安裝包_分布式執行jmeter腳本步驟(非GUI)

備注:【Linux查看服務器是32位還是64位命令】uname -mgetconf LONG_BIT1.Linux環境安裝jmeter可參考https://www.cnblogs.com/surewing/p/9271886.html如需要用到3臺客戶機,分別在三臺機器中安裝,以下安裝之前需安裝jdk環境1)將jm…

java mapreduce程序_簡單的java Hadoop MapReduce程序(計算平均成績)從打包到提交及運行...

[TOC]簡單的java Hadoop MapReduce程序(計算平均成績)從打包到提交及運行程序源碼import java.io.IOException;import java.util.Iterator;import java.util.StringTokenizer;import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.fs.Path;import org.apache…

python刪除列表一段元素_Python基礎--list列表刪除元素

列表中刪除元素主要分為以下 3 種場景: 根據目標元素所在位置的索引進行刪除,可以使用 del 關鍵字或者 pop() 方法; 根據元素本身的值進行刪除,可使用列表(list類型)提供的 remove() 方法; 將列…

microbit編程_使用圖形化編程實現主控板與手機藍牙通訊(2019.3.25)

本文轉自:DFRobot創客社區原文鏈接:[Mind]使用圖形化編程實現主控板與手機藍牙通訊-Mind論壇-DF創客社區?mc.dfrobot.com.cn本帖最后由 Forgotten 于 2019-3-25 12:58 編輯做項目時我們經常會遇到藍牙的問題,例如使用appinventor制作一個app…

山海伏妖錄java_山海伏妖錄攻略大全 劇情結局加點妖獸大全

山海伏妖錄是一款非常經典的ARPG游戲,其中有許多的劇情,結局,妖獸以及加點方案。Remilia為大家帶來山海伏妖錄攻略大全,各種攻略都能在這里查到,助您暢玩山海伏妖錄!山海伏妖錄人物介紹配角介紹山海伏妖錄結…

spark環境搭建java_Spark MLlib 環境搭建超詳細教程

1、系統及環境版本系統:Win7 旗艦版 64位 sp1JDK:1.8.0Spark:2.3.2Hadoop:2.7Scala:2.11.8文章最后,有所有版本的下載鏈接,不用再去折騰版本之間的問題。2、環境下載2.1 Spark 下載spark2.2 had…

python自動發郵件附件_python自動發送帶附件的郵件(163郵箱,親測可用)

1.設置發送郵件郵箱的SMTP服務 https://www.360kuai.com/pc/927b9f8da3555bb70?cota4&kuai_so1&tj_urlxz&sign360_57c3bbd1&refer_sceneso_1 設置步驟時,記住設置的郵箱的獨立密碼,在以下腳本中能夠用到2. python腳本 import smtplib f…

java 導出bcp文件格式_使用BCP導出導入數據

bcp 實用工具可以在 Microsoft SQL Server 實例和用戶指定格式的數據文件間大容量復制數據。 使用 bcp 實用工具可以將大量新行導入 SQL Server 表,或將表數據導出到數據文件。 除非與 queryout 選項一起使用,否則使用該實用工具不需要了解 Transact-SQL…

learnpythonthehardway下載_LearnPythonTheHardWay學習筆記1:學習環境搭建

覺得學習這本書應該有筆記,所以就從這里開始吧。 學習資料: 1.《笨辦法學Python》(承德-至陽整理 2013/7/19) 2.《Learn Python The Hard Way,3rd Edition》 (Zed A. Shaw 2010) 一、準備學習環境 &#xf…

java ajax多文件上傳插件_ajaxFileUpload.js插件支持多文件上傳的方法

前提條件:ajaxFileUpload.js插件多文件上傳步驟:1、修改源碼,(源碼只支持單個文件的上傳)://修改前代碼-------//var oldElement jQuery(# fileElementId);//var newElement jQuery(oldElement).clone();//jQuery(oldElement).…