基於 Data Mesh 構建分佈式領域驅動架構的最佳實踐

“所有數據歸人民”,這在企業裏是一個非常有吸引力的主張。然而,對於許多組織來說,快速解決集成問題,將數據提供給需要的人來解鎖洞察和創新還是一個遙遠的夢。

雖然遵守 GDPR 和 BCBS 239 等法規可能是一項挑戰,但它們只不過是現代數據平臺的最佳實踐指南。一個有遠見的組織應該有一個數據基礎結構(data fabric ),以解決常見的非功能需求,同時還要有一個運營模式,以識別數據的戰略價值。

本文介紹 Saxo 銀行如何藉助數據網格架構來實現這一願景。在數據平臺團隊的推動下,我們徹底地重新思考了組織內的數據使用情況。

大規模分佈式數據管理

雖然在過去二十年中,科技行業在大規模數據處理方面已經取得了長足的進步,但在很大程度上,仍然未能將數據管理擴展到組織層面。這既是工作方式的問題,也是技術變革的問題。簡而言之,從現在開始,我們要把數據當作一種產品來考慮,並考慮它是否容易發佈、發現、理解和消費。

自 2019 年 Zhamak Delgahni 首次提出這一概念以來,作爲一種架構範式,數據網格逐步獲得了人們的關注。2018 年底,Saxo 銀行開始實現一種新的數據架構,走上了類似的道路,我們很快就意識到,我們思路與數據網格非常相近。

圍繞 Delgahni 最初的設想,相關的文獻資料已經很多,本文不會再做這方面的討論。取而代之,我們將大概介紹下 Saxo 公司如何從數據網格的關鍵原則入手探索這一架構範式,如何將其變成現實,以及還面臨什麼挑戰。

分佈式領域驅動架構

  • 去中心化的聯合架構是與數據單體相對立的一種架構,它要求我們重新考慮數據的處理位置和所有權。

  • 數據網格規定,數據域應以一種易於消費的方式託管以及提供域數據集,而不是讓數據從不同的域流向一個集中式的數據湖或平臺。

自助服務平臺設計

  • 根據 2020 年 DevOps 現狀調查報告,DevOps 的高度發展與自主服務能力密切相關,因爲它使得團隊更高效,控制力更強,而平臺團隊可以專注於持續改進基礎設施。

  • 在這種情況下,Saxo 公司的自助服務平臺已經超越了純粹的基礎設施,專注於使域團隊能夠發佈自己的數據資產,以及使用其他團隊發佈的數據資產。

數據與產品思維相融合

  • 在 Saxo,我們認爲“數據即產品”,並且相信,產品的可用性與數據發現、理解和使用的難易度直接相關。我們鼓勵域數據團隊將產品思維運用到他們提供的數據集上,並且要將這項能力與其他能力一樣嚴肅對待。

分佈式領域驅動架構

Saxo 公司的主要數據域和其他投資銀行或經紀公司沒什麼不同。生產者相關的域如 trading 表示企業的交易(事實),主數據集如 party 提供此類域的上下文,消費者相關的域如 risk 往往會消費大量的數據,但生成的數據很少(如指標)。

圖 1:數據域

考慮到整個組織的變化節奏,我們知道,不能依靠一個集中式團隊來創建和填充一個典型的企業級數據模型。我們的方法必須能夠擴展。因此,我們將領域數據的所有權和它們的表示聯合起來,進行集中管理。

其中的挑戰在於,我們要確保整體大於部分(域會相互“齧合”,而非單獨存在)的總和。圖 2 是 Saxo 的數據運營模型。我們的治理目標是“恰好夠用”就行,即可以做到以下幾點:

  • 消費者與生產者解耦(事件優先於命令)。

  • 可以識別雙方都認可的權威數據源。

  • 要有一種標準的語言來確保信息在企業裏得到有效的使用;這種標準的或 "通用 "的語言是領域驅動設計(DDD)理念的核心,是消除開發人員和領域專家之間的溝通障礙的一種方法。

  • 其中,通用領域發揮着重要的作用,因爲我們希望可以標準化銀行中使用的一些基本概念。

我們是和數據辦公室的同事一起做這項工作,我們將此看成是一個好機會,可以恰當地錨定所有權(一般是在企業裏),並就每個領域的數據問題和策略展開對話。

圖 2:數據運營模型

1、領域團隊負責:

  • 識別數據集的權威數據源;

  • 創建相關數據模型;

  • 通過數據基礎結構將數據產品提供給其他團隊;

  • 修復數據質量(DQ)問題;問題應該在源頭處理,而不是在消費時。

2、企業數據架構師負責:

  • 策劃和設計,使領域數據成爲對 Saxo 銀行來說有長期價值的東西;

  • 領域物理模型變更審批;

  • 與領域團隊合作開發概念模型。

3、數據治理辦公室負責:

  • “激活”數據域,包括識別所有權、已知的數據質量問題等。

領域語言主要用於概念模型(挑戰在於要儘量輕量化)和物理模型(使用元數據進行修飾)。我們並不關心如何從概念圖生成物理模型,因爲我們認爲,這會將關注點從領域推理轉移到可視化編程上。

這個過程並不簡單,而且我們也只是剛剛開始。評審步驟無疑很重要,培訓和建立實踐社區也一樣。命名合理、文檔齊全、語義強類型、變化較小的模式很快就會得到批准。沒能做到這些的模式必然就需要更長的時間。

此外,在這個過程中,我們還認識到,我們不可能第一次就做對,領域模型需要持續的完善。事實上,企業數據架構師的角色也可以稱爲 "數據保管員"。學習、迭代和改進。

當然,運營模型是動態的,只是作爲某一時點的參考。

自助服務平臺設計

數據網格是一種技術無關的架構範式。在 Saxo,我們使用 Confluent 作爲數據基礎結構的基礎層——數據域的權威接口,以及比較傳統的請求 - 響應接口。

雖然 Apache Kafka®基於日誌的方式比較簡單,但是將其作爲企業中樞引入還是存在諸多挑戰。我們希望領域團隊可以不必考慮部署連接器、生成語言綁定以及如何處理個人身份數據等問題。考慮到開發平臺較多(以 C# 爲主,但與我們合作的團隊中也有使用 Python、C++ 以及 Kotlin 的),這不是件容易的事。

圖 3:Saxo 銀行的架構

我們的自助服務能力在很大程度上依賴於 GitOps,每個數據領域都通過以下兩個庫進行管理:

a、運營庫(Operational)

  • 主題配置,包括 ACL;

  • Kafka 連接器管理;

  • 數據質量規則,使用 Great Expectations DSL 表示。

b、模式庫(Schema)

  • Protobuf 模式驗證和審批;

  • 爲所有支持的語言生成代碼綁定,併發布到我們的工件庫。

可發現性不僅僅是指數據的結構,也是指讓整個銀行的數據專家瞭解數據產品的脈絡、所有權和相對健康狀況(表示爲一系列量化指標)。

爲此,元數據和指標都會發布到數據工作臺——基於 LinkedIn 的開源項目 DataHub 實現——使整個銀行的數據專家都能夠看到發佈到 Apache Kafka 的數據資產以及它們之間的關係。這方面還有很大的改進餘地,例如,在工具中管理元數據,而不是直接在模式文件中。

數據與產品思維相融合

(數據)產品的可用性可以歸結爲易於發現、理解和消費。集中式架構的一個優點是,很容易在不同的數據域中保持一致的用戶體驗,並確保用戶能夠將他們的心理模型從一個域遷移到另一個域。但是,我們的聯合架構需要一種完全不同的方法。

因此,在 Saxo,對於 Kafka 的使用,我們的自助服務平臺有自己的獨特之處。標準管道提供了一種跨所有領域的通用方法——樣式檢查、代碼綁定生成、數據質量規則執行 / 報告,以及元數據如何推送到數據工作臺等等。

我們儘量使數據資產能夠自我描述,並且概念描述清晰。我們的想法是在域內和域間使用同樣的元數據,提高數據的可用性,縮短新數據產品的上市時間。從根本上說,生產者的數據形狀預期不會有很大的變化,至少開始時是這樣。因爲很小的變化就會產生很大的影響:

  • 各領域都採用同樣的風格指南;

  • 特別注重強類型(“Currency”具有“string”所不具有的業務意義);

  • 只要可能就遵循行業標準;

  • 任何東西都有文檔記錄;

  • 禁用魔術值;

  • 從源頭獲取信息分類;

  • 鏈接相關概念。

然後,這些信息會通過數據工作臺暴露出來。在我們的實現中,數據工作臺扮演着重要的角色,不僅可以用於發現數據資產,而且讓我們可以從意義、所有權和質量方面瞭解每個數據域和資產,實現持續改進。

有效的模式

那麼,我們如何保證每個數據域的數據在外觀上保持一致呢?接下來的部分將介紹我們建議團隊在設計數據契約時參考的最佳實踐,首先從消息格式開始。

選擇一種格式

關於結構化數據的不同序列化機制的優點,已經有很多文章討論過了,例如 Martin Kleppmann 的文章“Avro 中的模式演變、Protocol Buffer 以及 Thrift”。通常,這些文章關注的都是模式管理和編碼效率。

我們經常忽略的是,語義註釋(又稱元數據)很容易嵌入到模式中。雖然 XSD(XML 的模式定義語言)的口碑並不好,但事實證明,像 FpML 這樣的標準在全球銀行業中的應用非常成功,因爲與其他方式相比,它們對消息定義有更嚴格的要求。事實上,鑑於 FpML 的開放性,許多人都以它爲基礎定義了自己的通用語言。

然而,由於 XML 已經不再是主流,我們研究了替代方案——特別是目前 Confluent 支持的方案:Avro、JSON 和 Protocol Buffer(Protobuf)。

在研究使用 JSON 編碼的可行性時,FpML 架構師工作組指出,用 JSON 根本無法表示同等多樣化的數據類型和語言約束。而且,小數需要編碼成字符串,這是唯一可靠的方式。此外,JSON Schema 沒有提供表達自定義語義註釋的方法。由於這些原因,我們沒有考慮使用 JSON Schema。

在這方面,Avro 的表現略勝一籌,尤其是與 Avro 接口定義語言(IDL)結合使用時,還提供了模式可組合性。我們可以將語義註釋表示成弱類型的 name-value 對,爲類型和字段添加額外的屬性。儘管 Avro 只定義了很少幾個原語,但經過擴展後,該語言已包含許多核心邏輯類型(小數、UUID、日期和時間)。

Protobuf 更進一步,允許通過 "自定義選項 "實現強消息類型和字段級註釋。這使得編譯時檢查成爲可能,這無疑是很好的。

另一個考慮是語言綁定的成熟度。Saxo 最開始選擇了 Avro,雖然不情願,但我們認識到,這會成爲主要的推廣障礙。儘管我們確實貢獻了一些修復(感謝 Matt Howlett 的支持),但 C# 和 Python 實現還是落後於 JVM,我們覺得,圍繞 C# 實現獲取支持會分散我們的注意力。

與 Avro 相比,Protobuf 的另一個優點是,對於類型和屬性,綁定將遵循目標語言的風格規範,而不受模式中使用的命名規範所影響。雖然這看起來是個小問題,但如果不適當地加以考慮,它就會成爲另一個阻力源。

2020 年底,我們最終切換到了 Protobuf,在 Confluent Schema Registry 將其作爲一等公民支持之後不久。當然,對於我們感興趣的語言綁定(C#、Python、C/C++,隨着 Kafka Streams 的關注度增加,還有 JVM),我們發現,這些實現要比 Avro 的一致性更好。

自描述模式

即使不瞭解 Protobuf 也沒關係,只要你掌握了錯綜複雜的 XSD,就會發現這很簡單。

簡單來說,複雜類型會被表示爲 "消息",而不管它是一個事件還是一個被事件引用的類型。儘管語法略有不同,但 "選項"(即語義註釋)可以在消息(類型)或字段(屬性)層面上表達。更多細節,請參閱《Proto3 語言指南》。

命名

命名很難,不過可以使用 Uber 的風格指南。該指南可以提供很好的一致性,並提供一種完善的方法來進行版本管理。

我們還有許多你在任何編碼標準中可能都會看到的準則。單數值的名字應該是單數的,複數字段的名字應該是複數的,等等。

文檔

所有記錄和屬性都需要在文檔中說明。即使看上去明顯的字段也經常有些細節不夠明顯。

標識符

企業標識符保持一致,是這種分佈式模式發揮作用的關鍵要求之一。畢竟,考慮到 Mesh 這個詞的含義:"在正確的位置連接在一起"。標識符可以唯一地標識一個實體,可以認爲是領域的 "主鍵",這也是我們實現數據網格的基本原則之一。

標識符是用 Protobuf IDL 定義的,如下所示:

// 以引用方式傳遞“Thing”

按照慣例,對於標識符的唯一屬性,我們將數字標識符命名爲 id,字母數字並用的標識符命名爲 code。對於各領域都有的企業標識符,必須以一種共同的方式來定義。

引用

引用(References )可以看成替代標識符,約束相對弱一些。例如,PaymentReference 可能是一個由客戶提供的自由格式的文本字段。下面是一個例子:

// 用戶提供的引用。不一定唯一。

按照慣例,對於引用的唯一屬性,我們將其命名爲 ref(通常是 string 類型)。企業引用必須以一種共同的方式來定義。

枚舉和方案

有些數據元素的值被限制爲只能是一組有限可能值中的一個。通常,這種有限值集被稱爲枚舉。

和許多其他語言類似,Protobuf 也支持枚舉類型。如果值的個數很少(例如小於 10 個),並且預計不會經常改變,那麼就可以使用 enum 類型。不過,一般來說,人們會希望類型參考一個外部編碼方案(coding scheme)(這個概念來自 FpML)。

如下所示,在 IDL 中引用方案:

// 根據ISO 3166標準,用三個字符的字母代碼表示貨幣。

在這個例子中,讀者被導向一個簡明的主題 reference-currency-compact-v1,這是貨幣代碼及其含義的權威列表。

方案不僅可以幫助接收方理解取值範圍,而且還爲數據質量自動監控創造了條件。理想情況下,模式會參考另一個主題,但如果團隊參考文檔,我們也會很高興。

信息分類

Saxo 定義了四種信息分類,每一類的敏感度都各不相同,模式中有體現,如下所示:

// 自然人的姓名

儘管我們希望體現在消息層面上,但有時候在在字段層面上進行表達可能更合理。在這種情況下,就要指定 field_info_class 選項。如果沒有說明,就會默認爲”僅內部 (internal only)“分類。

我們上雲的一項關鍵工作是確保 PII 數據經過加密。我們的最終目的是,直接通過模式註釋驅動加密,使開發團隊無需關注這些細節。

外部模式

雖然我們制定了關於 Protobuf 的標準,在某些情況下,我們也支持“引入自己的模式”。在這種情況下,具體的模式需要通過 external_schema 選項顯式引用:

// 外部模式示例

請注意,雖然由 vendor_string 表示的負載可能包含 third-party.xsd 的引用,但爲了便於“設計時”使用,必須在元數據中顯式引用。

棄用

棄用是演進過程中的必然產物,棄用可以讓消費者針對破壞性更改做好未來規劃。棄用可以在字段層或消息層上表示,如下所示:

// 屬性棄用示例

外部標準

應該如何表示一個電子郵件地址?一個日期?一個產品?一份監管文件?有可能已經有標準,有的話,我們就可以直接用。

只要可行,我們就會在文檔中引用這些標準,有時是作爲唯一定義,有時涉及 Saxo 的實現。我們通過 "業務術語 "選項,使用 term_source 和 term_ref 選項,將領域模型與外部標準聯繫起來,如下所示:

// 屬性棄用示例

顯然,在這個例子中,MonetaryAmount 的定義直接使用了金融業商業本體(Financial Industry Business Ontology)中的同名術語。11

術語鏈接

在我們迭代領域模型時,有些概念可能會在不同的數據域中重複。這是無意的,但也是不可避免的,不管前期再怎麼設計。爲了避免破壞性更改,我們需要一種機制,讓我們可以在不影響現有生產者或消費者的情況下引用已有的概念。

藉助 field_term_link 選項,我們可以將領域模型中的元素鏈接到行業術語的權威定義:

// “行業術語”鏈接示例

在這個例子中,trade_currency 引用了 "貨幣 "的通用表示,而且不會影響模式的兼容性。這不僅可以用來改進文檔,而且還可以作爲一份備忘錄,用於領域模型未來的迭代。

衡量標準

這種設計的價值在於,讓我們具備了進一步利用數據的能力。我們如何知道這條路是否正確?爲此,Saxo 已經識別出了一些指標,用於衡量願景實現的進展。

  • 網格中的連接數量(一個沒有連接的領域不可能產生廣泛的價值)

  • 生產者:消費比例

  • 創建滿足消費者需求的數據產品的提前期

  • 數據產品指標(如數據質量覆蓋率趨勢)

  • 測試覆蓋率(對變更的適應性)

  • 等等

未來展望

儘管 Saxo 已經在這些想法上做了一段時間的迭代,但只是在最近,在我們設法應對擴展挑戰的過程中,這種實現的應用才逐漸增多。我們主要關注的是:

  • 繼續降低進入平臺的障礙;

  • 提高平臺的附加值,例如通過自動對賬框架;

  • 和數據室以及整個銀行的同事一起工作,培養領域思維;

  • 繼續與 Acryl 以及 LinkedIn DataHub 社區合作,力爭使數據工作臺成爲所 有數據專家的一站式平臺:

  • 以領域爲中心的用戶界面;

  • 領域健康遊戲化;

  • 利用衆包方式改進模式文檔;

  • 在用戶界面中展示數據質量規則和結果;

  • 融合所有其他的上下游平臺;

  • 使團隊可以方便地使用類似 ksqlDB 這樣的工具。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章