我們最近想設計一個新的資料處理架構,預計可能會有一個新服務,公司內部叫它 operational warehouse,它的功能是可以"跨資料庫去讀取資料"。此外,它主要是用於營運系統而不是分析系統,換言之,它容許的資料延時很短。
友人問了這個問題。
我一開始沒有多想,我只注意到 warehouse 一詞,聯想到的是一些分析領域常用的解決方案,所以我回答:
如果用 CDC 的處理架構做,比方說 Debezium ,資料延時是超短,但是,開發維護成本偏高。
看要不要考慮 trino 這類的 SQL engine?這類解法的話,需要資料的時候才去撈資料…。
很快地,我開始後悔我一開始給友人的想法了,因為友人告訴我更多細節…。
我們公司的後端軟體系統,考慮到團隊分工與資料庫可擴展性,正在逐步演變成微服務模式,而且是一服務一資料庫 (service per database) 的微服務模式。
一旦真的改成這樣子時,需要跨不同資料庫查詢或是寫入的操作,就會變得複雜,所以我在考慮,要設計一個專門的服務,即前述的 operational warehouse 來處理,又或是也實做看看 saga 之類的模式?
聽到了這邊,我大概覺得有掌握問題的核心了。
首先,這個微服務系統將來可能會產生大量的程式碼需要開發。原因是,只要一用到跨資料庫的寫入或是讀取,都會需要開發許多的程式碼,而且這些程式碼都是在處理『同步』,而『同步』(concurrency) 本來是資料庫就可以完成的事。換言之,前述的『微服務模式』會將資料庫底層的複雜度,拉到上層,恰恰好違反了 "pulling the complexity downwards" 的設計原則。
綜合以上,我認為:
最好不要使用一服務一資料庫 (service per database) 的微服務模式。資料庫有可擴展性需求的話,看要不要改用 NewSQL 資料庫,至少可以把『同步的複雜度』,留在資料庫這一層裡。做了微服務、接著被迫又得開發分散式查詢與寫入,無異於讓複雜度從資料庫層上昇到應用程式層,絕非好的方向。
設計模式與設計原則
設計模式 (Pattern) 在軟體開發的許多領域都常常出現,比方說,在物件導向程式設計,有一本書:《設計模式:可復用物件導向軟體的基礎》;在微服務的領域,也有各種不同的微服務設計模式。一般而言,設計模式來自觀察與歸納,專家很可能一次又一次觀察到了特定的模式 (pattern) 重複出現,於是就把這些模式加以精鍊、整理出來。
設計原則 (Design Principle) 則是比設計模式更加抽象的東西,往往是從大量的成功案例之中,歸納出來的成功原則。有時候,除了歸納之外,也有不少的演繹成分。有些設計原則,可以找得到科學的理由,有些甚至可以應用到其它不同的領域。
在我的經驗,當設計模式 (pattern) 與設計原則 (principle) 衝突時,十之八九,都可以找到另一種不應用該模式且更好的解決方案。發生衡突,多數的時候,都是設計原則勝出。