##微服務(wù)架構(gòu)下的分布式數(shù)據(jù)管理

干貨丨微服務(wù)架構(gòu)下的分布式數(shù)據(jù)管理 https://mp.weixin.qq.com/s/WYNrcBe0h_o7whRGxqsqwg

本文詳細(xì)的介紹了分布式數(shù)據(jù)管理的各種舉措和一些應(yīng)用案例,具有很強(qiáng)的實(shí)戰(zhàn)指導(dǎo)作用。

1.1 分布式數(shù)據(jù)管理之痛點(diǎn)

為了確保微服務(wù)之間松耦合,每個(gè)服務(wù)都有自己的數(shù)據(jù)庫(kù), 有的是關(guān)系型數(shù)據(jù)庫(kù)(SQL),有的是非關(guān)系型數(shù)據(jù)庫(kù)(NoSQL)。
開(kāi)發(fā)企業(yè)事務(wù)往往牽涉到多個(gè)服務(wù),要想做到多個(gè)服務(wù)數(shù)據(jù)的一致性并非易事,同樣,在多個(gè)服務(wù)之間進(jìn)行數(shù)據(jù)查詢也充滿挑戰(zhàn)。
我們以一個(gè)在線B2B商店為例,客戶服務(wù) 包括了客戶的各種信息,例如可用信用等。
管理訂單,提供訂單服務(wù),則需要驗(yàn)證某個(gè)新訂單與客戶的信用限制沒(méi)有沖突。
在單體應(yīng)用中,訂單服務(wù)只需要使用傳統(tǒng)事務(wù)交易就可以一次性檢查可用信用和創(chuàng)建訂單。
相反微服務(wù)架構(gòu)下,訂單和客戶表分別是相應(yīng)服務(wù)的私有表,如下圖所示:

訂單服務(wù)不能直接訪問(wèn)客戶表,只能通過(guò)客戶服務(wù)發(fā)布的API來(lái)訪問(wèn)或者使用分布式事務(wù), 也就是眾所周知的兩階段提交 (2PC)來(lái)訪問(wèn)客戶表,2PC意義圖如下所示:

這里存在兩個(gè)挑戰(zhàn),第一個(gè)挑戰(zhàn)是2PC除要求數(shù)據(jù)庫(kù)本身支持外,還要求服務(wù)的數(shù)據(jù)庫(kù)類型需要保持一致。
但是現(xiàn)在的微服務(wù)架構(gòu)中,每個(gè)服務(wù)的數(shù)據(jù)庫(kù)類型可能是不一樣的,有的可能是MySQL數(shù)據(jù)庫(kù),有的也可能是NoSQL數(shù)據(jù)庫(kù);
第二個(gè)挑戰(zhàn)是如何實(shí)現(xiàn)從多個(gè)服務(wù)中查詢數(shù)據(jù)。假設(shè)應(yīng)用程序需要顯示一個(gè)客戶和他最近的訂單。如果訂單服務(wù)提供用于檢索客戶訂單的API,那么應(yīng)用程序端可以通過(guò)JOIN方式來(lái)檢索此數(shù)據(jù),即應(yīng)用程序首選從客戶服務(wù)檢索客戶,并從訂單服務(wù)檢索客戶的訂單。
然而,如果訂單服務(wù)僅支持通過(guò)其主鍵查找訂單(也許它使用僅支持基于主鍵的檢索的NoSQL數(shù)據(jù)庫(kù)), 在這種情況下,就沒(méi)有方法來(lái)檢索查詢所需的數(shù)據(jù)。
為解決這兩大痛點(diǎn),就需要我們使用到分步式數(shù)據(jù)管理了。

1.2 分布式數(shù)據(jù)管理之舉措

在介紹分布式數(shù)據(jù)管理(CRUD)解決方案之前,有必要介紹下CAP原理和最終一致性相關(guān)概念。

1.2.1 CAP原理和最終一致性

1.2.1.1 CAP原理(CAP Theorem)

在足球比賽里,一個(gè)球員在一場(chǎng)比賽中進(jìn)三個(gè)球,稱之為帽子戲法(Hat-trick)。在分布式數(shù)據(jù)系統(tǒng)中,也有一個(gè)帽子原理(CAP Theorem),不過(guò)此帽子非彼帽子。CAP原理中,有三個(gè)要素:
1)一致性(C onsistency)
2)可用性(A vailability)
3)分區(qū)容忍性(P artition tolerance)
CAP原理指的是,這三個(gè)要素最多只能同時(shí)實(shí)現(xiàn)兩點(diǎn),不可能三者兼顧。
因此在進(jìn)行分布式架構(gòu)設(shè)計(jì)時(shí),必須做出取舍。而對(duì)于分布式數(shù)據(jù)系統(tǒng),分區(qū)容忍性是基本要求 ,否則就失去了價(jià)值,因此設(shè)計(jì)分布式數(shù)據(jù)系統(tǒng),就是在一致性和可用性之間取一個(gè)平衡。
對(duì)于大多數(shù)web應(yīng) 用,其實(shí)并不需要強(qiáng)一致性,因此犧牲一致性而換取高可用性,是目前多數(shù)分布式數(shù)據(jù)庫(kù)產(chǎn)品的方向。
當(dāng)然,犧牲一致性,并不是完全不管數(shù)據(jù)的一致性,否則數(shù)據(jù)是混亂的,那么系統(tǒng)可用性再高分布式再好也沒(méi)有了價(jià)值。
犧牲一致性,只是不再要求關(guān)系型數(shù) 據(jù)庫(kù)中的強(qiáng)一致性,而是只要系統(tǒng)能達(dá)到最終一致性即可,考慮到客戶體驗(yàn),這個(gè)最終一致的時(shí)間窗口,要盡可能的對(duì)用戶透明,也就是需要保障“用戶感知到的一致性”。
通常是通過(guò)數(shù)據(jù)的多份異步復(fù)制來(lái)實(shí)現(xiàn)系統(tǒng)的高可用和數(shù)據(jù)的最終一致性的,“用戶感知到的一致性”的時(shí)間窗口則 取決于數(shù)據(jù)復(fù)制到一致?tīng)顟B(tài)的時(shí)間。

1.2.1.2 最終一致性(eventually consistent)

對(duì)于一致性,可以分為從客戶端和服務(wù)端兩個(gè)不同的視角。
從客戶端來(lái)看,一致性主要指的是多并發(fā)訪問(wèn)時(shí)更新過(guò)的數(shù)據(jù)如何獲取的問(wèn)題。
從服務(wù)端來(lái)看,則是更新如何復(fù)制分布到整個(gè)系統(tǒng),以保證數(shù)據(jù)最終一致。
一致性是因?yàn)橛胁l(fā)讀寫才有的問(wèn)題,因此在理解一致性的問(wèn)題時(shí),一定要注意結(jié)合考慮并發(fā)讀寫的場(chǎng)景。
從客戶端角度,多進(jìn)程并發(fā)訪問(wèn)時(shí),更新過(guò)的數(shù)據(jù)在不同進(jìn)程如何獲取的不同策略,決定了不同的一致性。
對(duì)于關(guān)系型數(shù)據(jù)庫(kù),要求更新過(guò)的數(shù)據(jù)能被后續(xù)的 訪問(wèn)都能看到,這是強(qiáng)一致性 ;如果能容忍后續(xù)的部分或者全部訪問(wèn)不到,則是弱一致性 ; 如果經(jīng)過(guò)一段時(shí)間后要求能訪問(wèn)到更新后的數(shù)據(jù),則是最終一致性。
從服務(wù)端角度,如何盡快將更新后的數(shù)據(jù)分布到整個(gè)系統(tǒng),降低達(dá)到最終一致性的時(shí)間窗口,是提高系統(tǒng)的可用度和用戶體驗(yàn)非常重要的方面。
那么問(wèn)題來(lái)了,如何實(shí)現(xiàn)數(shù)據(jù)的最終一致性呢?答案就在事件驅(qū)動(dòng)架構(gòu)。

1.2.2 事件驅(qū)動(dòng)架構(gòu)簡(jiǎn)介

Chris Richardson作為微服務(wù)架構(gòu)設(shè)計(jì)領(lǐng)域的權(quán)威,給出了分布式數(shù)據(jù)管理的最佳解決方案。
對(duì)于大多數(shù)應(yīng)用而言,要實(shí)現(xiàn)微服務(wù)的分布式數(shù)據(jù)管理,需要采用事件驅(qū)動(dòng)架構(gòu)(event-driven architecture)。
在事件驅(qū)動(dòng)架構(gòu)中,當(dāng)某件重要事情發(fā)生時(shí),微服務(wù)會(huì)發(fā)布一個(gè)事件,例如更新一個(gè)業(yè)務(wù)實(shí)體。
當(dāng)訂閱這些事件的微服務(wù)接收此事件時(shí),就可以更新自己的業(yè)務(wù)實(shí)體,也可能會(huì)引發(fā)更多的事件發(fā)布,讓其他相關(guān)服務(wù)進(jìn)行數(shù)據(jù)更新,最終實(shí)現(xiàn)分布式數(shù)據(jù)最終一致性。
可以使用事件來(lái)實(shí)現(xiàn)跨多服務(wù)的業(yè)務(wù)交易。交易一般由一系列步驟構(gòu)成,每一步驟都由一個(gè)更新業(yè)務(wù)實(shí)體的微服務(wù)和發(fā)布激活下一步驟的事件構(gòu)成。

1.2.2.1 事件驅(qū)動(dòng)示例1

下圖展現(xiàn)如何使用事件驅(qū)動(dòng)方法,在創(chuàng)建訂單時(shí)檢查信用可用度,微服務(wù)之間通過(guò)消息代理(Messsage Broker)來(lái)交換事件。

  1. 訂單服務(wù)創(chuàng)建一個(gè)帶有NEW狀態(tài)的Order (訂單),發(fā)布了一個(gè)“Order Created Event(創(chuàng)建訂單)”的事件。
  1. 客戶服務(wù) 消費(fèi)Order Created Event事件,為此訂單預(yù)留信用,發(fā)布“Credit Reserved Event(信用預(yù)留)”事件。
  1. 訂單服務(wù)消費(fèi)Credit Reserved Event,改變訂單的狀態(tài)為OPEN。

1.2.2.2 事件驅(qū)動(dòng)示例2
下圖展現(xiàn)如何使用事件驅(qū)動(dòng)方法,在創(chuàng)建訂單時(shí)觸發(fā)支付業(yè)務(wù)的數(shù)據(jù)更新,微服務(wù)之間通過(guò)消息代理(Messsage Broker)來(lái)交換事件。

  1. 訂單服務(wù)創(chuàng)建一個(gè)待支付的訂單,發(fā)布一個(gè)“創(chuàng)建訂單”的事件。
  1. 支付服務(wù)消費(fèi)“創(chuàng)建訂單”事件,支付完成后發(fā)布一個(gè)“支付完成”事件。
  1. 訂單服務(wù)消費(fèi)“支付完成”事件,訂單狀態(tài)更新為待出庫(kù)。

1.2.3 事件驅(qū)動(dòng)架構(gòu)之分布式數(shù)據(jù)更新
上節(jié)通過(guò)示例概要介紹了通過(guò)事件驅(qū)動(dòng)方式,實(shí)現(xiàn)了分布式數(shù)據(jù)最終一致性保證。縱觀微服務(wù)架構(gòu)下的事件驅(qū)動(dòng)業(yè)務(wù)處理邏輯,其核心要點(diǎn)在于,可靠的事件投遞和避免事件的重復(fù)消費(fèi)。
可靠事件投遞有以下兩個(gè)特性:

  1. 每個(gè)服務(wù)原子性的完成業(yè)務(wù)操作和發(fā)布事件;
  2. 消息代理確保事件投遞至少一次(at least once);
    而避免事件重復(fù)消費(fèi)則要求消費(fèi)事件的服務(wù)實(shí)現(xiàn)冪等性,比如支付服務(wù)不能因?yàn)橹貜?fù)收到事件而多次支付。
    BTW:當(dāng)前流行的消息隊(duì)列如Kafka等,都已經(jīng)實(shí)現(xiàn)了事件的持久化和at least once的投遞模式,所以可靠事件投遞的第二條特性已經(jīng)滿足,這里就不展開(kāi)。接下來(lái)章節(jié)講重點(diǎn)講述如何實(shí)現(xiàn)可靠事件投遞的第一條特性和避免事件重復(fù)消費(fèi),即服務(wù)的業(yè)務(wù)操作和發(fā)布事件的原子性和避免消費(fèi)者重復(fù)消費(fèi)事件要求服務(wù)實(shí)現(xiàn)冪等性。
    1.2.3.1 如何實(shí)現(xiàn)事件投遞操作原子性?
    事件驅(qū)動(dòng)架構(gòu)會(huì)碰到數(shù)據(jù)庫(kù)更新和發(fā)布事件原子性問(wèn)題。例如,訂單服務(wù)必須向ORDER表插入一行,然后發(fā)布Order Created event,這兩個(gè)操作需要原子性。比如更新數(shù)據(jù)庫(kù)后,服務(wù)癱了(crashes)造成事件未能發(fā)布,系統(tǒng)變成不一致?tīng)顟B(tài)。那么如何實(shí)現(xiàn)服務(wù)的業(yè)務(wù)操作和發(fā)布事件的原子性呢?
    1.2.3.1.1 使用本地事務(wù)發(fā)布事件
    獲得原子性的一個(gè)方法是將服務(wù)的業(yè)務(wù)操作和發(fā)布事件放在一個(gè)本地?cái)?shù)據(jù)庫(kù)事務(wù)里,也就是說(shuō),需要在本地建立一個(gè)EVENT表,此表在存儲(chǔ)業(yè)務(wù)實(shí)體數(shù)據(jù)庫(kù)中起到消息列表功能。當(dāng)應(yīng)用發(fā)起一個(gè)(本地)數(shù)據(jù)庫(kù)交易,更新業(yè)務(wù)實(shí)體狀態(tài)時(shí),會(huì)向EVENT表中插入一個(gè)事件,然后提交此次交易。另外一個(gè)獨(dú)立應(yīng)用進(jìn)程或者線程查詢此EVENT表,向消息代理發(fā)布事件,然后使用本地交易標(biāo)志此事件為已發(fā)布,如下圖所示:

訂單服務(wù)向ORDER表插入一行,然后向EVENT表中插入Order Created event,事件發(fā)布線程或者進(jìn)程查詢EVENT表,請(qǐng)求未發(fā)布事件,發(fā)布他們,然后更新EVENT表標(biāo)志此事件為已發(fā)布。
此方法也是優(yōu)缺點(diǎn)都有。優(yōu)點(diǎn)是可以確保事件發(fā)布不依賴于2PC,應(yīng)用發(fā)布業(yè)務(wù)層級(jí)事件而不需要推斷他們發(fā)生了什么;而缺點(diǎn)在于此方法由于開(kāi)發(fā)人員必須牢記發(fā)布事件,因此有可能出現(xiàn)錯(cuò)誤。
1.2.3.1.2 使用事件源
Event sourcing (事件源)通過(guò)使用以事件中心的數(shù)據(jù)存儲(chǔ)方式來(lái)保證業(yè)務(wù)實(shí)體的一致性。事件源保存了每個(gè)業(yè)務(wù)實(shí)體所有狀態(tài)變化的事件,而不是存儲(chǔ)實(shí)體當(dāng)前的狀態(tài)。應(yīng)用可以通過(guò)重放事件來(lái)重建實(shí)體現(xiàn)在的狀態(tài)。只要業(yè)務(wù)實(shí)體發(fā)生變化,新事件就會(huì)添加到事件表中。因?yàn)楸4媸录菃我徊僮鳎虼丝隙ㄊ窃有缘摹?br> 為了理解事件源工作方式,考慮以事件實(shí)體作為一個(gè)例子說(shuō)明。傳統(tǒng)方式中,每個(gè)訂單映射為ORDER表中一行。但是對(duì)于事件源方式,訂單服務(wù)以事件狀態(tài)改變方式存儲(chǔ)一個(gè)訂單:創(chuàng)建的,已批準(zhǔn)的,已發(fā)貨的,取消的;每個(gè)事件包括足夠信息來(lái)重建訂單的狀態(tài)。

事件源方法有很多優(yōu)點(diǎn):解決了事件驅(qū)動(dòng)架構(gòu)關(guān)鍵問(wèn)題,使得業(yè)務(wù)實(shí)體更新和事件發(fā)布原子化,但是也存在缺點(diǎn),因?yàn)槭浅志没录皇菍?duì)象,導(dǎo)致數(shù)據(jù)查詢時(shí),必須使用 Command Query Responsibility Segregation (CQRS) 來(lái)完成查詢業(yè)務(wù),從開(kāi)發(fā)角度看,存在一定挑戰(zhàn)。
1.2.3.2 如何避免事件重復(fù)消費(fèi)?
要避免事件重復(fù)消費(fèi),需要消費(fèi)事件的服務(wù)實(shí)現(xiàn)服務(wù)冪等,因?yàn)榇嬖谥卦嚭湾e(cuò)誤補(bǔ)償機(jī)制,不可避免的在系統(tǒng)中存在重復(fù)收到消息的場(chǎng)景,服務(wù)冪等能提高數(shù)據(jù)的一致性。在編程中,一個(gè)冪等操作的特點(diǎn)是其任意多次執(zhí)行所產(chǎn)生的影響均與一次執(zhí)行的影響相同,因此需要開(kāi)發(fā)人員在功能設(shè)計(jì)實(shí)現(xiàn)時(shí),需要特別注意服務(wù)的冪等性。

1.2.4 事件驅(qū)動(dòng)架構(gòu)之分布式數(shù)據(jù)查詢
微服務(wù)架構(gòu)下,由于分布式數(shù)據(jù)庫(kù)的存在,導(dǎo)致在執(zhí)行用戶業(yè)務(wù)數(shù)據(jù)查詢時(shí),通常需要跨多個(gè)微服務(wù)數(shù)據(jù)庫(kù)進(jìn)行數(shù)據(jù)查詢,也就是分布式數(shù)據(jù)查詢。那么問(wèn)題來(lái)了,由于每個(gè)微服務(wù)的數(shù)據(jù)都是私有化的,只能通過(guò)各自的REST接口獲取,如果負(fù)責(zé)業(yè)務(wù)查詢的功能模塊,通過(guò)調(diào)用各個(gè)微服務(wù)的REST接口來(lái)分別獲取基礎(chǔ)數(shù)據(jù),然后在內(nèi)存中再進(jìn)行業(yè)務(wù)數(shù)據(jù)拼裝后,再返回給用戶。該方法無(wú)論從程序設(shè)計(jì)或是查詢性能角度看,都不是一個(gè)很好的方法。那么如何解決微服務(wù)架構(gòu)下的分布式數(shù)據(jù)查詢問(wèn)題呢? 在給出解決方案之前,需要讀者首先了解下物化視圖和命令查詢職責(zé)分離等相關(guān)概念。
1.2.4.1 什么是物化視圖(merialized views)?
物化視圖是包括一個(gè)查詢結(jié)果的數(shù)據(jù)庫(kù)對(duì)像,它是遠(yuǎn)程數(shù)據(jù)的的本地副本,或者用來(lái)生成基于數(shù)據(jù)表求和的匯總表。物化視圖存儲(chǔ)基于遠(yuǎn)程表的數(shù)據(jù),也可以稱為快照。這個(gè)基本上就說(shuō)出了物化視圖的本質(zhì),它是一組查詢的結(jié)果,這樣勢(shì)必為將來(lái)再次需要這組數(shù)據(jù)時(shí)大大提高查詢性能。物化視圖有兩種刷新模式ON DEMAND和ON COMMIT,用戶可根據(jù)實(shí)際情況進(jìn)行設(shè)置。
物化視圖對(duì)于應(yīng)用層是透明的,不需要有任何的改動(dòng),終端用戶甚至都感覺(jué)不到底層是用的物化視圖。總之,使用物化視圖的目的一個(gè)是提高查詢性能,另一個(gè)是由于物化視圖包含的數(shù)據(jù)是遠(yuǎn)程數(shù)據(jù)庫(kù)的數(shù)據(jù)快照或拷貝,微服務(wù)可通過(guò)物化視圖和命令查詢職責(zé)分離(CQRS)技術(shù)(參見(jiàn)以下章節(jié))實(shí)現(xiàn)分布式數(shù)據(jù)查詢。
1.2.4.2 什么是命令查詢職責(zé)分離(CQRS)?
在常用的單體應(yīng)用架構(gòu)中,通常都是通過(guò)數(shù)據(jù)訪問(wèn)層來(lái)修改或者查詢數(shù)據(jù),一般修改和查詢使用的是相同的實(shí)體。在一些業(yè)務(wù)邏輯簡(jiǎn)單的系統(tǒng)中可能沒(méi)有什么問(wèn)題,但是隨著系統(tǒng)邏輯變得復(fù)雜,用戶增多,這種設(shè)計(jì)就會(huì)出現(xiàn)一些性能問(wèn)題;另外更重要的是,在微服務(wù)架構(gòu)下,通常需要跨多個(gè)微服務(wù)數(shù)據(jù)庫(kù)來(lái)查詢數(shù)據(jù),此時(shí),我們可借助命令查詢職責(zé)分離(CQRS)來(lái)有效解決這些問(wèn)題。
CQRS使用分離的接口將數(shù)據(jù)查詢操作(Queries)和數(shù)據(jù)修改操作(Commands)分離開(kāi)來(lái),這也意味著在查詢和更新過(guò)程中使用的數(shù)據(jù)模型也是不一樣的。這樣讀和寫邏輯就隔離開(kāi)來(lái)了。使用CQRS分離了讀寫職責(zé)之后,可以對(duì)數(shù)據(jù)進(jìn)行讀寫分離操作來(lái)改進(jìn)性能,同時(shí)提高可擴(kuò)展性和安全。如下圖:

主數(shù)據(jù)庫(kù)處理CUD,從庫(kù)處理R,從庫(kù)的的結(jié)構(gòu)可以和主庫(kù)的結(jié)構(gòu)完全一樣,也可以不一樣,從庫(kù)主要用來(lái)進(jìn)行只讀的查詢操作。在數(shù)量上從庫(kù)的個(gè)數(shù)也可以根據(jù)查詢的規(guī)模進(jìn)行擴(kuò)展,在業(yè)務(wù)邏輯上,也可以根據(jù)專題從主庫(kù)中劃分出不同的從庫(kù)。從庫(kù)也可以實(shí)現(xiàn)成ReportingDatabase,根據(jù)查詢的業(yè)務(wù)需求,從主庫(kù)中抽取一些必要的數(shù)據(jù)生成一系列查詢報(bào)表來(lái)存儲(chǔ)。

使用ReportingDatabase的一些優(yōu)點(diǎn)通常可以使得查詢變得更加簡(jiǎn)單高效:
· ReportingDatabase的結(jié)構(gòu)和數(shù)據(jù)表會(huì)針對(duì)常用的查詢請(qǐng)求進(jìn)行設(shè)計(jì)。
· ReportingDatabase數(shù)據(jù)庫(kù)通常會(huì)去正規(guī)化,存儲(chǔ)一些冗余而減少必要的Join等聯(lián)合查詢操作,使得查詢簡(jiǎn)化和高效,一些在主數(shù)據(jù)庫(kù)中用不到的數(shù)據(jù)信息,在ReportingDatabase可以不用存儲(chǔ)。
· 可以對(duì)ReportingDatabase重構(gòu)優(yōu)化,而不用去改變操作數(shù)據(jù)庫(kù)。
· 對(duì)ReportingDatabase數(shù)據(jù)庫(kù)的查詢不會(huì)給操作數(shù)據(jù)庫(kù)帶來(lái)任何壓力。
· 可以針對(duì)不同的查詢請(qǐng)求建立不同的ReportingDatabase庫(kù)。
1.2.4.3 如何實(shí)現(xiàn)事件驅(qū)動(dòng)架構(gòu)下的數(shù)據(jù)查詢服務(wù)?
事件驅(qū)動(dòng)不僅可以用于分布式數(shù)據(jù)一致性保證,還可以借助物化視圖和命令查詢職責(zé)分離技術(shù),使用事件來(lái)維護(hù)不同微服務(wù)擁有數(shù)據(jù)預(yù)連接(pre-join)的物化視圖,從而實(shí)現(xiàn)微服務(wù)架構(gòu)下的分布式數(shù)據(jù)查詢。維護(hù)物化視圖的服務(wù)訂閱了相關(guān)事件并在事件發(fā)生時(shí)更新物化視圖。例如,客戶訂單視圖更新服務(wù)(維護(hù)客戶訂單視圖)會(huì)訂閱由客戶服務(wù)和訂單服務(wù)發(fā)布的事件(您還可以使用事件來(lái)維護(hù)由多個(gè)微服務(wù)擁有的數(shù)據(jù)組成的物化視圖。 維護(hù)該視圖的服務(wù)訂閱了相關(guān)事件來(lái)觸發(fā)更新該物化視圖)。

例如上圖中間的 “客戶訂單視圖更新”服務(wù),主要負(fù)責(zé)客戶訂單視圖的更新。該服務(wù)訂閱了客戶服務(wù)和訂單服務(wù)發(fā)布的事件。當(dāng)“客戶訂單視圖更新”服務(wù)收到了上圖左側(cè)的客戶或者訂單更新事件,則會(huì)觸發(fā)更新客戶訂單物化視圖數(shù)據(jù)集。這里可以使用文檔數(shù)據(jù)庫(kù)(例如MongoDB)來(lái)實(shí)現(xiàn)客戶訂單視圖,為每個(gè)用戶存儲(chǔ)一個(gè)文檔。而上圖右側(cè)的客戶訂單視圖查詢服務(wù)負(fù)責(zé)響應(yīng)對(duì)客戶以及最近訂單(通過(guò)查詢客戶訂單視圖數(shù)據(jù)集)的查詢。
總之,上圖所示業(yè)務(wù)邏輯,用到了事件驅(qū)動(dòng)、物化視圖和命令查詢職責(zé)分離等技術(shù),有效解決了微服務(wù)架構(gòu)下分布式數(shù)據(jù)查詢的問(wèn)題。

1.2.5 事件驅(qū)動(dòng)架構(gòu)優(yōu)缺點(diǎn)
事件驅(qū)動(dòng)架構(gòu)既有優(yōu)點(diǎn)也有缺點(diǎn),此架構(gòu)可以實(shí)現(xiàn)跨多個(gè)服務(wù)的事務(wù)實(shí)現(xiàn),且提供最終數(shù)據(jù)一致性,并且使得服務(wù)能夠自動(dòng)維護(hù)查詢視圖;而缺點(diǎn)在于編程模式比傳統(tǒng)基于事務(wù)的交易模式更加復(fù)雜,必須實(shí)現(xiàn)補(bǔ)償事務(wù)以便從應(yīng)用程序級(jí)故障中恢復(fù),例如,如果信用檢查不成功則必須取消訂單;另外,應(yīng)用必須應(yīng)對(duì)不一致的數(shù)據(jù),比如當(dāng)應(yīng)用讀取未更新的最終視圖時(shí)也會(huì)遇見(jiàn)數(shù)據(jù)不一致問(wèn)題。另外一個(gè)缺點(diǎn)在于訂閱者必須檢測(cè)和忽略冗余事件,避免事件重復(fù)消費(fèi)。

1.3 總結(jié)
在微服務(wù)架構(gòu)中,每個(gè)微服務(wù)都有自己私有的數(shù)據(jù)集。不同微服務(wù)可能使用不同的SQL或者NoSQL數(shù)據(jù)庫(kù)。盡管數(shù)據(jù)庫(kù)架構(gòu)有很強(qiáng)的優(yōu)勢(shì),但是也面對(duì)數(shù)據(jù)分布式管理的挑戰(zhàn)。第一個(gè)挑戰(zhàn)就是如何在多服務(wù)之間維護(hù)業(yè)務(wù)數(shù)據(jù)一致性;第二個(gè)挑戰(zhàn)是如何從多服務(wù)環(huán)境中獲取一致性數(shù)據(jù)。
最佳解決辦法是采用事件驅(qū)動(dòng)架構(gòu)。其中碰到的一個(gè)挑戰(zhàn)是如何原子性的更新?tīng)顟B(tài)和發(fā)布事件。有幾種方法可以解決此問(wèn)題,包括將數(shù)據(jù)庫(kù)視為消息隊(duì)列和事件源等。
從目前技術(shù)應(yīng)用范圍和成熟度看,推薦使用第一種方式(本地事務(wù)發(fā)布事件),來(lái)實(shí)現(xiàn)事件投遞原子化,即可靠事件投遞。
需要提醒:!!!數(shù)據(jù)一致性是微服務(wù)架構(gòu)設(shè)計(jì)中唯恐避之不及卻又不得不考慮的話題。通過(guò)保證事件驅(qū)動(dòng)實(shí)現(xiàn)最終數(shù)據(jù)的一致性,此方案的優(yōu)劣,也不能簡(jiǎn)單的一言而概之,而是應(yīng)該根據(jù)場(chǎng)景定奪,適合的才是最好的。另外,我們?cè)趯?duì)微服務(wù)進(jìn)行業(yè)務(wù)劃分的時(shí)候就盡可能的避免“可能會(huì)產(chǎn)生一致性問(wèn)題”的設(shè)計(jì)。如果這種設(shè)計(jì)過(guò)多,也許是時(shí)候考慮改改設(shè)計(jì)了。

1.4 參考資料
https://www.nginx.com/blog/event-driven-data-management-microservices/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,963評(píng)論 6 542
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,348評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 178,083評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 63,706評(píng)論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,442評(píng)論 6 412
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 55,802評(píng)論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,795評(píng)論 3 446
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 42,983評(píng)論 0 290
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,542評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,287評(píng)論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,486評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,030評(píng)論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,710評(píng)論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 35,116評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 36,412評(píng)論 1 294
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,224評(píng)論 3 398
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,462評(píng)論 2 378

推薦閱讀更多精彩內(nèi)容