譯者 | 楊曉娟
策劃 | 云昭
系統中的數據遠比構成系統的應用程序本身更有價值,這似乎有點老生常談。應用程序會更新、變革、失效和替換,但數據仍然存在。對許多組織來說,這些數據是他們最重要的資產。過去很簡單,你有組織的數據庫,只有一個地方存放著組織的所有信息,從這里可以獲取所有想要的內容。一個用于管理、監控、優化、備份等的數據庫—負責承接整個組織的數據需求。
隨著組織的發展,數據不斷增長,因而越來越多的需求被添加到數據庫中。在某一時刻,就會觸及極限。使用單一數據庫的做法已經力不從心,必須將系統和數據庫分解為獨立的組件。在本文中,將討論如何管理數據范圍和大小的增長。
1.共享數據庫的消亡,為什么不能使用更大的機器
雖然并不常見,但目前有數十億條記錄達到萬億字節范圍的數據庫并不少見。那么有什么問題呢?問題不在于特定數據庫引擎的技術限制。而是組織將所有東西放入單個數據庫。例如,在我工作過的一家公司,數據庫中有超過30,000多張表,視圖和存儲過程的數量更多,這還沒說觸發器的數量。
沒有哪個數據庫工具能夠處理如此數量的表。GUI工具每次連接數據庫時總會導致該工具卡頓幾分鐘,同時它會在短時間內讀取模式描述。沒有人清楚數據庫內部發生了什么,但是數據和圍繞它的流程對組織的成功至關重要。最后的結果:要么停滯不前,要么開始將數據庫分成可管理的組成部分。
那是多年前的事了,行業格局已經發生了改變。今天,當我們考慮數據時,有更多問題需要考慮,例如:
- 屬于歐洲公民的個人數據,這意味著與他們相關的任何數據也必須實際存儲于歐盟,并受GDPR規則的約束。
- 醫療保健信息(直接或間接),需要遵循一套全新的規則(例如,HIPAA、HITECH或ENISA規則)。
數據隱私和出處等問題更為重要,比如能夠審計和分析誰訪問了某個特定數據項,以及為什么它在許多領域都是一個硬性要求。組織中的所有信息都駐留在一個存儲桶中的概念已不再可行。
另一個重要的巨變是常見的架構模式。我們現在不再使用單一的龐大系統來管理組織中的一切內容,而是將系統分解成更小的組件。這些組件有不同的需要和需求,按不同的時間表發布,使用不同的技術。當你想更改自己的系統時,嘗試在所有這些團隊之間進行協調的巨大開銷是你想要在系統中進行更改的一個大障礙。跨這么多團隊和組件進行協調的成本太高了。
通常的想法是使用獨立應用程序數據庫,而非單個共享數據庫。這是一個更大的架構概念的重要組成部分。通常會在微服務和面向服務的體系結構中碰到這種情況。
2.應用程序數據庫作為實現決策
從單個共享數據庫遷移到一組應用程序數據庫之間一個最重要的區別是沒有拆分共享數據庫。數據庫級別的適當分離是關鍵。一組共享數據庫也會有完全相同的協調問題,因為廚房里有太多的廚師。應用程序數據庫被正確地分離,就能夠為每個任務選擇最佳的數據庫引擎,本地化更改,減少溝通更改的開銷。這種方法的缺點是在生產中要支持更多系統。
我們來更深入地討論下共享數據庫與應用程序數據庫之間的區別。很容易弄錯,例如圖1所示:
圖1:從單個共享數據庫到多個(仍然共享)數據庫的錯誤遷移路徑
雖然共享數據庫是你實現的,因為沒有其他選擇,但應用程序數據庫是內部選擇,除了應用程序沒有人能訪問。與面向對象編程的封裝有相同的含義,使用私有變量隱藏狀態,非常確定的是,應用程序數據庫是應用程序之外任何事物都不必關心的問題。我對此深有同感。
編寫代碼時,直接使用其他對象的私有狀態是錯誤的。如果違反了不變性,未來的維護和開發都會變復雜。這已經被大量事實敲定,因此大多數開發人員幾乎本能地不會這么做。直接訪問另一個應用程序的數據庫也會發生完全相同的狀況,但卻非常常見。
在某些情況下,我對數據庫中所有表和列的名稱進行了加密,以表明你不應該查看我的數據庫。應用程序數據庫應該僅僅是應用程序的內部關注點。這個想法很簡單。如果應用程序之外的任何實體需要一些數據,則需要向應用程序請求。他們不應該直接進入應用程序數據庫獲取。這是詢問“你在和誰說話”與查看他們所有的交流記錄及留言之間的區別。理論上,這是一個好方法,但是需要考慮到,你的應用程序不僅是系統的應用程序,還必須與生態系統的其他部分集成。問題是你如何做到這一點。
如果這里描述的系統聽起來很熟悉,那是因為你可能以前聽說過。它最初是DCOM/COBRA系統的一部分,后來被稱為面向服務的體系架構,現在被稱為微服務。
假設在我們的系統中處理發貨的應用程序需要訪問一些客戶數據來完成其任務。如何獲得這些數據?使用共享數據庫時,直接查詢客戶表。當負責客戶應用程序的團隊需要添加列或重構數據時,你的系統就會遭到破壞。它們之間沒有封裝或分離。直接依賴另一個團隊的實現細節的方式會導致破壞、停滯和不斷增加的復雜性。
3.使用全局數據
或者,發貨應用程序可以(通過已發布的服務接口)請求擁有客戶數據的應用程序以獲取所需的詳細信息。這通常是通過從一個應用程序到另一個應用程序的RCP調用來完成。問題是,如此一來就在兩個應用程序之間建立了牢固的聯系。如果客戶的應用程序因維護而停機,則運輸應用程序將無法工作。再加上幾十個這樣的應用程序及其相互依賴關系,你就有可能陷入僵局。我們需要考慮一種更好的方法來處理這種情況。
我的建議是從另一個方向著手整個過程。發貨應用程序不必查詢客戶應用程序的相關數據,而是進行相反的操作。作為客戶應用程序服務接口的一部分,完全可以決定要向組織的其他部分公開什么樣的信息。
需要注意的是,發布的數據絕對是服務契約的一部分。不提供對數據庫的直接訪問。應用程序應該向外界發布其數據。可以是上傳到FTP站點或GraphQL端點的每日CSV文件,以選擇兩種截然不同的技術和語義。
我在FTP上包含了CSV,以特別表明數據共享的方式是無關緊要的。重要的是,有一種從應用程序發布數據的既定方式,因為這種架構風格的一個關鍵方面是不必在需要的時候查詢數據。相反,我們將其攝取到自己的系統中。我想很明顯,為什么發貨應用程序不會打開一個FTP連接到客戶的每日CSV轉儲文件以查找詳細信息。同樣的,它也不應該將查詢GraphQL端點作為其常規例程的一部分。
相反,我們有一個既定的機制,通過該機制發布客戶的數據(客戶應用程序已向組織的其他部分公開)。這由系統中的其它應用程序攝取,當他們需要查詢客戶的詳細信息時,可以從自己的系統中進行查詢。如圖2所示:
圖2:客戶應用程序發布數據以供運輸應用程序使用
在每個應用程序中,數據可以以不同的方式存儲和表示。在每種情況下,都是最適合他們的。
發布應用程序還可以以他們選擇的任何方式處理數據。數據庫和數據發布方式之間的服務邊界允許自由修改內部細節,而無需與外部系統協調。
另一個選擇是采用兩階段的流程,如圖3所示。客戶應用程序不必將其更新發送給發貨應用程序,而是將其發送到組織數據湖。通過這種方式,每個應用程序將希望公開的數據發送到一個中心位置。其他應用程序可以將需要的數據從數據湖復制到自己的數據庫中。
圖3:每個應用程序發布數據到數據湖并拉取數據到各應用程序
最終結果是一個共享數據的系統,但是沒有應用程序和服務之間的時間依賴關系。它還確保了不同團隊和系統之間的邊界。只要發布的接口保持不變,就不需要協調增加復雜性。
4.實踐中的幾個建議
我們深入探討關于如何應用這種體系架構方法的一些具體建議。可以通過在服務總線上發出事件或發布每日文件來全局發布數據。可以發布特定場景的數據,例如從客戶數據庫到發貨數據庫的ETL流程。只要有適當的邊界,局部的方法的改變將對整體的影響度很低。
這種操作方式只在需要引用數據或對與一致性無關的數據做出決策時有效。如果需要對數據進行更改或協調更改,則此方法不適用。一致性無關緊要的一個很好的例子就是根據客戶的ID查找他們的名字,如果我們有舊名字,那不是什么大問題。很快就會自行修復,我們不會根據客戶的名字來做決定。同時,我們可以在應用程序范圍內完全本地運行所有的計算和任務,這是一個很大的優勢。
當我們需要做出決定或修改數據時,一致性很重要。例如,在發貨場景中,如果要收取超重費,需要確保客戶賬戶中有足夠的資金。在這種情況下,我們并不擁有賬戶中的資金,不能對自己的數據進行操作。如此一來,需要向客戶發起應用程序申請,要求扣除這些資金,如果資金不足,則報告錯誤。注意,如果客戶無法付款,更合理的結果應該是:發貨操作失敗。
應用程序不應該再部署到單個服務器甚至單個數據中心。如今,在邊緣系統上運行應用程序(如移動應用程序或物聯網設備)已經非常常見。將所有這些數據推送到自己的系統中可能會導致存儲不可承受的巨量數據。數據封裝和僅公開希望公開的細節這種架構風格在這個場景中發揮得非常好。
無需將所有信息復制到中心位置,而是將數據存儲在邊緣,并從邊緣設備接收足夠的數據,以便能夠做出決策并操作系統的全局狀態。除其他優點外,這種方法讓用戶可以掌控他們所有的數據,我認為這是一個主要的優點
5.寫在最后
在架構中使用應用程序數據庫和顯式數據發布有幾個原因。首先,它意味著操作是以本地資源和最少的協調運行的。反過來,意味著這些操作更快、更可靠。其次,它減少了整個系統的協調開銷,這表明可以根據需要獨立部署和更改每個應用程序。
最后,它意味著可以獨立地為每個場景選擇最佳選項。可以為每個選項選擇最好的品種,而不是迎合最低公分母。例如,可以使用文檔數據庫來存儲發貨清單,而將歷史數據放入數據湖中。
每個應用程序都是獨立的,彼此隔離,可以為每個場景做出最佳的技術選擇,而不必考慮任何全局約束。其結果是一個更易修改的系統,由更小的組件組成(因而更容易理解),并且更加敏捷。
譯者介紹
楊曉娟,51CTO社區編輯,資深研發工程師,信息系統項目管理師。
原文鏈接:
??https://dzone.com/articles/data-management-in-complex-systems???