為什么說(shuō)集中管理數(shù)據(jù)是個(gè)壞主意?
微服務(wù)架構(gòu)是現(xiàn)代應(yīng)用程序和系統(tǒng)的一個(gè)常見(jiàn)模型。其特點(diǎn)是把一個(gè)大型應(yīng)用的業(yè)務(wù)責(zé)任分割成不同的、獨(dú)立的組件,可以獨(dú)立開(kāi)發(fā)、管理、操作和擴(kuò)展。
微服務(wù)架構(gòu)為應(yīng)用程序本身的擴(kuò)展提供了一個(gè)有效的模型,允許更大的、更不連貫的開(kāi)發(fā)團(tuán)隊(duì)獨(dú)立完成他們的部分工作,同時(shí)仍然參與大型應(yīng)用程序的構(gòu)建中。
在一個(gè)典型的微服務(wù)架構(gòu)中,單獨(dú)的服務(wù)被創(chuàng)建,該服務(wù)包含了一個(gè)特定的業(yè)務(wù)邏輯子集。當(dāng)相互連接時(shí),整個(gè)微服務(wù)集形成一個(gè)完整的、大規(guī)模的應(yīng)用程序,包含完整的業(yè)務(wù)邏輯。
這種模式對(duì)代碼來(lái)說(shuō)是很好的,但對(duì)數(shù)據(jù)呢?通常,為特定業(yè)務(wù)邏輯創(chuàng)建單獨(dú)服務(wù)的公司覺(jué)得有必要把所有的應(yīng)用數(shù)據(jù)放到一個(gè)單一的、集中的數(shù)據(jù)存儲(chǔ)中。這個(gè)想法是為了確保所有的數(shù)據(jù)對(duì)可能需要它的每個(gè)服務(wù)都是可用的。管理單個(gè)數(shù)據(jù)存儲(chǔ)很容易,也很方便,而且數(shù)據(jù)建模對(duì)整個(gè)應(yīng)用程序來(lái)說(shuō)是一致的,與使用它的服務(wù)無(wú)關(guān)。
不要這樣做,集中你的數(shù)據(jù)是一個(gè)壞主意。這里有三個(gè)原因:
集中的數(shù)據(jù)很難擴(kuò)展
當(dāng)整個(gè)應(yīng)用程序的數(shù)據(jù)都在一個(gè)集中的數(shù)據(jù)存儲(chǔ)中時(shí),隨著應(yīng)用程序的增長(zhǎng),你必須擴(kuò)展整個(gè)數(shù)據(jù)存儲(chǔ)以滿足應(yīng)用程序中所有服務(wù)的需求。這顯示在圖1的左邊。如果你為每個(gè)服務(wù)使用單獨(dú)的數(shù)據(jù)存儲(chǔ),只有需求增加的服務(wù)需要擴(kuò)展,而被擴(kuò)展的數(shù)據(jù)庫(kù)是一個(gè)較小的數(shù)據(jù)庫(kù)。這在圖1的右邊顯示。
將小型數(shù)據(jù)庫(kù)擴(kuò)展到更大的規(guī)模要比將大型數(shù)據(jù)庫(kù)擴(kuò)展到更大的規(guī)模容易得多。

圖1. 按服務(wù)劃分?jǐn)?shù)據(jù)可以簡(jiǎn)化擴(kuò)展
集中的數(shù)據(jù)以后很難分割
新開(kāi)發(fā)應(yīng)用程序的開(kāi)發(fā)者通常的想法是:“我現(xiàn)在不需要擔(dān)心擴(kuò)展的問(wèn)題,在以后需要的時(shí)候再擔(dān)心吧”。這種觀點(diǎn)雖然很普遍,但在某些時(shí)候卻會(huì)導(dǎo)致擴(kuò)展問(wèn)題。當(dāng)應(yīng)用程序變得流行時(shí),你必須重新思考架構(gòu)決策,以滿足客戶(hù)的增量需求。
一個(gè)常見(jiàn)的架構(gòu)變化是需要將你的數(shù)據(jù)存儲(chǔ)分割成更小的數(shù)據(jù)存儲(chǔ)。問(wèn)題是,在應(yīng)用程序剛創(chuàng)建時(shí)比在應(yīng)用程序生命周期的后期更容易進(jìn)行分割。當(dāng)應(yīng)用程序已經(jīng)存在了幾年,并且應(yīng)用程序的所有部分都可以訪問(wèn)對(duì)應(yīng)的數(shù)據(jù)時(shí),要確定數(shù)據(jù)集的哪些部分可以被分割成一個(gè)單獨(dú)的數(shù)據(jù)存儲(chǔ)而不需要對(duì)使用數(shù)據(jù)的代碼進(jìn)行重大重寫(xiě)就變得非常困難。即使是簡(jiǎn)單的問(wèn)題也變得很困難。哪些服務(wù)在使用Profiles表?是否有服務(wù)同時(shí)需要系統(tǒng)表和項(xiàng)目表?
而且,更糟糕的是,是否有任何服務(wù)使用這兩個(gè)表來(lái)執(zhí)行連接?它的用途是什么?在代碼中的什么地方完成的?我們?cè)鯓硬拍苤貥?gòu)這種變化?
一個(gè)數(shù)據(jù)集在一個(gè)數(shù)據(jù)存儲(chǔ)中停留的時(shí)間越長(zhǎng),以后就越難把這個(gè)數(shù)據(jù)存儲(chǔ)分成更小的部分。
通過(guò)將數(shù)據(jù)按功能分成獨(dú)立的數(shù)據(jù)存儲(chǔ),你可以避免以后將數(shù)據(jù)從連接的表中分離出來(lái)的相關(guān)問(wèn)題,也可以減少代碼中存在的數(shù)據(jù)之間意外關(guān)聯(lián)的可能性。
集中的數(shù)據(jù)使數(shù)據(jù)所有權(quán)無(wú)法實(shí)現(xiàn)
將數(shù)據(jù)劃分為多個(gè)服務(wù)的一大優(yōu)勢(shì)是能夠?qū)?yīng)用所有權(quán)劃分為不同的、可分離的部分。單個(gè)開(kāi)發(fā)團(tuán)隊(duì)的應(yīng)用程序所有權(quán)是現(xiàn)代應(yīng)用開(kāi)發(fā)的一個(gè)核心原則,它可以促進(jìn)更好的組織擴(kuò)展,并在問(wèn)題發(fā)生時(shí)提高響應(yīng)能力。這種所有權(quán)模式在面向單一團(tuán)隊(duì)的服務(wù)架構(gòu)(STOSA)開(kāi)發(fā)模式中進(jìn)行了討論。
當(dāng)你有大量的開(kāi)發(fā)團(tuán)隊(duì)都在為一個(gè)大型的應(yīng)用程序做貢獻(xiàn)時(shí),這種模式非常有效,但即使是有較小團(tuán)隊(duì)的小型應(yīng)用程序也能從這種模式中受益。
問(wèn)題是,一個(gè)團(tuán)隊(duì)要擁有一個(gè)服務(wù)的所有權(quán),他們必須同時(shí)擁有該服務(wù)的代碼和數(shù)據(jù)。這意味著一個(gè)服務(wù)(服務(wù)A)不應(yīng)該直接訪問(wèn)另一個(gè)服務(wù)(服務(wù)B)的數(shù)據(jù)。如果服務(wù)A需要存儲(chǔ)在服務(wù)B中的東西,它必須調(diào)用服務(wù)B的一個(gè)服務(wù)入口點(diǎn),而不是直接訪問(wèn)該數(shù)據(jù)。

圖2. 服務(wù)A永遠(yuǎn)不應(yīng)該直接訪問(wèn)服務(wù)B的數(shù)據(jù)
這允許服務(wù)B對(duì)其數(shù)據(jù)、如何存儲(chǔ)以及如何維護(hù)擁有完全的自主權(quán)。
那么,有什么選擇呢?當(dāng)你構(gòu)建面向服務(wù)的架構(gòu)(SOA)時(shí),每個(gè)服務(wù)應(yīng)該擁有自己的數(shù)據(jù)。這些數(shù)據(jù)是服務(wù)的一部分,并被納入服務(wù)中。

圖3. 每個(gè)服務(wù)都有自己的數(shù)據(jù)
這樣,服務(wù)的所有者可以管理該服務(wù)的數(shù)據(jù)。如果需要對(duì)數(shù)據(jù)進(jìn)行模式改變或其他結(jié)構(gòu)性改變,服務(wù)所有者可以在沒(méi)有任何其他服務(wù)所有者參與的情況下實(shí)現(xiàn)更改。隨著應(yīng)用程序(及其服務(wù))的增長(zhǎng),服務(wù)所有者可以做出擴(kuò)展決策和數(shù)據(jù)重構(gòu)決策,以處理增加的負(fù)載和變化的需求,而無(wú)需其他服務(wù)所有者的參與。
一個(gè)問(wèn)題經(jīng)常出現(xiàn),那些真正需要在應(yīng)用程序之間共享的數(shù)據(jù)怎么辦?諸如用戶(hù)配置文件數(shù)據(jù),或其他在應(yīng)用程序的許多常用的數(shù)據(jù)。一個(gè)誘人的快速解決方案可能是只在多個(gè)服務(wù)之間共享所需的數(shù)據(jù),如圖4所示。每個(gè)服務(wù)可能有它自己的數(shù)據(jù),同時(shí)也可以訪問(wèn)共享的數(shù)據(jù)。

圖4. 不建議在服務(wù)之間共享數(shù)據(jù)
更好的方法是將共享數(shù)據(jù)放入一個(gè)由所有其他服務(wù)使用的新服務(wù)中,如圖5所示。

圖5. 使用服務(wù)是訪問(wèn)共享數(shù)據(jù)的正確方式
服務(wù)C這一新的服務(wù)也應(yīng)該遵循STOSA的要求。特別是,它應(yīng)該有一個(gè)單一的、明確的團(tuán)隊(duì)來(lái)?yè)碛性摲?wù),從而擁有共享數(shù)據(jù)。如果任何其他服務(wù),如圖中的服務(wù)A或服務(wù)B,需要訪問(wèn)共享數(shù)據(jù),它必須通過(guò)服務(wù)C提供的API來(lái)實(shí)現(xiàn)。這樣,服務(wù)C的所有者是唯一負(fù)責(zé)共享數(shù)據(jù)的團(tuán)隊(duì),可以就擴(kuò)展、重構(gòu)和更新方面做出適當(dāng)?shù)臎Q策。只要維護(hù)一個(gè)一致的API供服務(wù)A和服務(wù)B使用,服務(wù)C就可以做出任何關(guān)于更新數(shù)據(jù)的決定。
這與圖4相反,圖4中服務(wù)A和服務(wù)B都直接訪問(wèn)共享數(shù)據(jù)。在這個(gè)模型中,沒(méi)有一個(gè)團(tuán)隊(duì)可以在不涉及直接訪問(wèn)數(shù)據(jù)的所有其他團(tuán)隊(duì)的情況下對(duì)數(shù)據(jù)的結(jié)構(gòu)、布局、擴(kuò)展或建模做出任何決定,這限制了應(yīng)用程序開(kāi)發(fā)過(guò)程的可擴(kuò)展性。
使用微服務(wù)或其他SOA是管理從事大型應(yīng)用的大型開(kāi)發(fā)團(tuán)隊(duì)的一個(gè)好方法。但是,服務(wù)架構(gòu)也必須包含應(yīng)用程序的數(shù)據(jù),否則真正的服務(wù)獨(dú)立性--也就是開(kāi)發(fā)組織的擴(kuò)展獨(dú)立性--將不可能實(shí)現(xiàn)。
作者:Lee Atchison是云計(jì)算和應(yīng)用現(xiàn)代化領(lǐng)域公認(rèn)的思想領(lǐng)袖。Lee在產(chǎn)品開(kāi)發(fā)、架構(gòu)、擴(kuò)展和現(xiàn)代化方面有三十多年的經(jīng)驗(yàn),曾在亞馬遜、亞馬遜網(wǎng)絡(luò)服務(wù)(AWS)、New Relic和其他現(xiàn)代應(yīng)用組織工作。