從業務數據庫到元數據,SaaS架構設計經驗全總結

SaaS可以說是軟件交付方式演化路徑中必需的一環,它的存在有其社會意義與必然性,這是社會動力體系的經濟屬性中成本驅動力誘發的。SaaS也是算力與網絡發展的必然,隨着算力與網絡帶寬的極大提高,這個世界的計算樣態可能都會改變,未來有些場景可能更趨於中央計算(核心算力都在雲上,接入的設備不需要很強的算力,甚至僅爲終端)。SaaS在中國正以其自有的節奏穩步發展中,筆者曾深度參與過三個SaaS項目的工作,本文力求從實用的角度分享一些關於SaaS架構的經驗要點,所謂自見者不明、自是者不彰,希望能借此文與各位讀者有進一步的交流。

未來社會模型中SaaS的位置與分量

上圖是一個從連接這個透視角度抽象出來的社會模型,其中的家庭、人、組織、物都是相互連接的,它也是一個從軟件架構抽象出來的社會模型。SaaS是對軟件的獲得和使用方式的革命,早在2004年就已有端倪(當時稱爲ASP,Application Service Provider)。筆者認爲,可以將SaaS放在社會運行機制、發展趨勢這樣的大格局中定位其社會作用。SaaS企業也需要這樣的格局與信念,雖然在中國還沒有出現非常成功的SaaS企業,但終究會出現的,信任、習慣、規範、與能力都需要進化,需要時間。

在沒有電之前,人們就有傳遞信息的需求,這也是爲什麼微信能夠存在的本質根由。同理,各種組織都離不開軟件,而且軟件的滲透越來越廣泛與深入,因爲整個世界的數字化是不可阻擋的趨勢。而SaaS在大部分情況下是必選之路,會越來越成爲標配,除非特殊原因,或者不在乎成本、或者已經擁有某種等效的軟件、或者其他原因。只要這種本質性的需求存在着,社會的發展終究會以越來越先進的方式來滿足它。

這裏分享一個關於雲的小故事,筆者曾經算過一筆賬,如果在雲上訂購託管機房中約500臺機器的同等算力,每年需要支出5000萬,相當有悖於流行認知,其實對於稍微有些規模的IT資源訴求,雲相對是更加昂貴的,但來的快、方便,兩方面都是事實。

這裏只想傳遞一個觀點,長遠來看,SaaS有它存在與發展的必然性。結構上講,它是社會運行機制中不可或缺的一部分。同樣或者類似的軟件,顯然沒有必要每個人、每個組織都各買一套或各自開發一套,這是社會資源的極大浪費,有悖於社會發展的基本規律——既然是必需的,必然選擇物美價廉。而且組織支出比個人支出更理性、更注重實用價值,有利可圖的需求終究會達到穩態的、某種主流服務的滿足。

從架構角度看SaaS面臨的挑戰

如果說SaaS在大部分情況下將會成爲必選之路,那麼它面臨的最大挑戰又是什麼呢?概括來講,SaaS面臨的最大挑戰是滿足客戶的個性化需求。從架構角度看,它體現在如下圖所示的幾個方面:

其中最有挑戰性的又要屬多變的後臺邏輯與數據模型。對於SaaS供應商而言,這種需求顯然不能通過項目的方式來定製滿足,而只有通過提供靈活的自服務平臺才能滿足,這種靈活性就需要用PaaS來生產客戶想要的軟件。這一點筆者在2013年做一個SaaS項目的架構工作時就深有體會:一開始的目標也是做SaaS,但是後來還是走上了PaaS的道路,不過是專爲生產SaaS而自用的PaaS,而不是定位於PaaS供應商。

如果一個SaaS企業從一開始就只是聚焦某個業務,而沒有着手PaaS的建設,那說明它在滿足個性化需求的道路上一定是在某個局部、某個層面解決問題,而不是系統、全面、可複用地解決問題。同時,從中國SaaS市場現狀來看,它的成長比較慢,環境的綜合成熟度還不夠高,聚焦單一業務成長的加速度不夠,因此企業後續很可能會從最開始聚焦的核心業務向外擴展,到時候又要面臨種種個性化需求問題。因此,一個成功的SaaS企業必然要去尋求PaaS的支撐。從這兩個意義上講,PaaS可能也是SaaS企業提高生產力的必經方向。據有關數據表明,在企業棄用SaaS的原因中,無法滿足個性化需求佔了23%,可見PaaS的支撐多麼重要。

如何做好SaaS架構?

1 業務數據庫

SaaS,特別是To B的時候,業務數據庫必然是存儲的核心,這裏筆者針對業務數據庫總結了一些架構層面的建議。

建議一:對於任何mission critical的場景都要使用RDBMS

企業應用與To C的使用場景有一個明顯的區別是,絕大部分情況下,它對正確性、準確性的要求更高,而且SaaS提供方需要對此承擔相應的責任。因此,支撐一線黃金業務流程的數據庫目前來看還是得使用關係型數據庫。目前來看有兩個開源可選項,分別是MySQL和PostgreSQL。

建議二:分庫

支持多租戶可以有多種方式,這裏所說的分庫並不是指每個租戶一個獨立的庫(當然產品銷售時可以作爲套餐的一個選項),而是指多個數據庫實例,每個實例包含多個租戶的完整數據。

說到多租戶,需要提個醒,通常大家都會想當然地認爲租戶之間是隔離的,但是事情都有另一面,對於大集團客戶,在某些業務上,它的分公司、子集團之間可能還是有連接的。另外,人員組織機構建模上,也要考慮一個人任職多個子集團或公司的可能。

建議三:Partitioning

即使是一個數據庫實例,也可以再繼續分區,MySQL和PostgreSQL(至少版本11以上)都支持在一個實例內部分區。對租戶進行Partitioning可以在一定程度上提高性能,因爲把一個查詢限制在更小的數據範圍內進行,而非全量數據空間,效率自然會更高。

建議四:元數據驅動,Salesforce不是標杆

一個民族、一個國家如果沒有非權威精神,是不會有根本性創新的。動則大廠是如何做的,好像大廠總是做的最好的,那是不行的,盲目崇拜只能是follower,不可能是creator,當然也不能盲目忽視,最要緊的是把業務架構搞清楚、明確定義到底要什麼。心裏要有譜,但是技術本身絕對不是譜,而僅僅是可選的手段。

以下是根據Salesforce官網資料整理的的核心數據模型:

其業務數據表本身是沒有物理索引的,真正的索引主要在MT_Indexes中,但是這有點讓人困惑,爲什麼不在MT_Data上直接建立物理索引呢?難道列和索引太多了會影響性能?而反範式地單獨以列的方式、按數據類型建立很少的索引就好?爲此,筆者動手做了驗證。

1)實驗條件

爲了聚焦在問題本身,圖 3中只採用了綠色的兩張表,而省略了紅色的字段,本實驗所使用的字段名和圖 3不一樣,但是思路是一樣的。

  • OS,Windows 10;

  • DB,MySQL 5.7;

  • 兩張業務表,有物理索引的=bizdata,沒有物理索引的=bizdata2,結構如下:

  • bizdata和bizdata2都灌入了10萬條數據,字符型長度爲4,它的值基於給定的一個長度爲10的字符串隨機生成,數值型的則爲100以內的隨機數;

  • 索引表爲pivot_index,其中rowid的值等於業務表中id的值,col是列名,它們可能的值是c1-c5、n1-n5,string_value和int_value分別容納的是字符型和數值型的業務數據值,總的數據行數是100萬行。

2)實驗結果

以下比較,除了SQL形態上不一樣,從語義上講,條件與期望的結果都是完全一樣的。彙總如下:

# 方式 結果(秒)
1 MT_Data(自身無物理索引) + MT_Indexes,Salesforce方式 5.39
2 MT_Data(自身有物理索引) 0.05
3 MT_Data(自身無物理索引) 0.13
4 MT_Data(自身無物理索引),且字符字段都採用條件 like ‘%xxxx%’ 0.16

使用Salesforce索引表(相當於業務數據表MT_Data上沒有物理索引,紅框部分爲行變列的pivot邏輯,其實紅框外的條件在都是or的情況下是可以省略的,否則不可以,這裏僅僅爲了體現邏輯完整結構,Salesforce後臺用的是Oracle,也許性能比MySQL好不少,也許Oracle有pivot的核武器,不過從邏輯上講,就算給Oracle更大的想象空間,行數倍增也是不爭的事實)的結果:

直接使用物理索引(相當於業務數據表MT_Data上有物理索引)的結果:

直接使用沒有物理索引的業務數據表(相當於不考慮MT_Indexes)的結果:

在沒有使用物理索引的bizdata上用’%xxx%’,看情況如何:

3)實驗結論

結論是不要採用Salesforce的元數據使用方式,因爲其行列轉換的性能損失相當大。此例相當於把數據行數放大了10倍,顯然在業務數據表上直接建索引更可取。當然,Salesforce的情況可能有其歷史原因,或者它有某種未知的核武器。本文建議採用如下模型:

其實,Salesforce對於查詢是有限制的,如果它消耗的資源太大,會直接拋異常。很可能它是依據提取數據的行數的閾值或者時間(governor limits,資源裁判的角色)來限制的,因此它的性能還是有一定的侷限性。官網對此表述爲:“被優化器認爲資源開銷過大的個別查詢會拋出異常給調用方,儘管這聽起來有點嚴格,但爲了保護數據庫系統總體的可伸縮性和性能,這是必要的。”

建議五:索引所有字段

Salesforce的做法是讓租戶自己決定一個字段是否要索引,但筆者認爲在硬件越來越廉價的今天,如果要在用戶體驗與成本之間平衡,用戶體驗更可取。不過Salesforce也會自動爲特定字段建索引,參見這裏。

其實軟件這東西,從用戶接受層面上講,在根植於中國文化的市場上是有點障礙的。例如:字段field,這個詞對於中國大部分普通人來說是很陌生的,但是對於以英語爲母語的市場而言,說“請把這個表格填一下”,然後說“包括每一個field”,則是一件很普通的事情。當我們交付一個產品的時候,需要站在用戶的角度去體驗、思考、感受,而不能假設所有人都有和軟件開發人員一樣的認知背景。

建議六:PostgreSQL優於MySQL

這裏不是要對二者做詳盡的比較,而是瞄準一個核心點,元數據驅動的定製能力。由於MySQL的row size是有限制的,65535字節,而PostgreSQL的限制則爲1GB,顯然後者有更廣闊的空間,這也是推薦圖 10業務數據模型的原因之一。

建議七:深挖數據庫本身的優化空間

對於PostgreSQL,相信還有很多潛力可以挖掘,筆者暫未對其做過深入研究,這裏只給出一個方向。例如:它支持sub-partition,假設在用OrgID分區的前提下,再進一步用年來分區,對於有些數據的性能可能會更進一步提升,不過無法保證這個可行,凡有得必有失。

再比如,在MySQL中,通常可能認爲插入一條數據沒啥可優化的,就是通常見到的那種寫法,但是,insert into table_1 set a=a1,b=b2這樣的寫法據說是最高效的。

諸如此類,結合多租戶、元數據驅動的特點,可能還有很多值得挖掘的地方,最可靠的方法是完整研讀官網、對多種值得關注的選項動手試一試。

2 搜索

搜索是SaaS必須具備的一種能力,例如:輸入關鍵詞,希望系統能找出附件中出現這些關鍵詞的合同,不管附件的格式如何。搜索和通常RDBMS的全文檢索是完全不同的,儘管在某些技術思路上是一樣的,但具體實現的能力差別很大。因此,SaaS系統必須提供存在於關係型數據庫之外單獨的搜索系統。

這裏仍以Saleforce爲例展開說明。Salesforce對於空間非常吝嗇,對於任何一個用戶自定義字段,是否建索引、是否可以搜索,都把選擇權留給用戶。其實這麼做從用戶體驗上看並不好,而且對於普通用戶,一般對於搜索與查詢沒有很強的技術性概念,在選擇時就會存在困惑。因此,更可取的做法可能是,對於可能需要搜索的,就讓它都能搜索。但是,有一個基本的問題要回答,那就是結果集從哪裏來?

如果結果集中同時包含來自關係型數據庫和搜索引擎的數據,並讓用戶在定製過程中選擇各個字段的結果都從哪裏來,對用戶體驗可能不大好。但我們可以這麼做,讓最終用戶在已經完成定製併發布的功能中選擇,在高級查詢界面專門開闢出搜索條件區域,讓用戶輸入關鍵詞和搜索範圍即可。

上圖左側的模式,搜索引擎返回的是ID列表,需要組合兩個引擎的能力。這就要求平臺有自己的查詢引擎和優化器,基本邏輯是先識別出搜索部分,然後把結果組裝到原來的查詢語句中,最後提交給RDBMS來處理。

這裏補充一個建議,對於用戶上傳的附件,只要可以轉換爲文本,也把它送到搜索引擎,用戶在定義業務實體的時候可以不指定要不要可搜索,但是在構建查詢功能的時候,可以由用戶來決定是不是對某些字段執行搜索。

由於目前的開源搜索引擎(至少Elasticsearch是這樣的)還不能保證聚合的準確性和不丟失數據,因此對於潛在的丟失數據的問題,在架構上可以考慮:

3 元數據

把對元數據的理解侷限於表及其屬性、字段及其屬性,是不夠的。其實把元數據稱爲模型驅動更合適,它可以包含PaaS或SaaS中那些所有由客戶自己創建的軟件要素的模型,例如:郵件模型、界面模型、佈局模型、API模型、流程模型等。其實人類認識世界、改造世界,根本上就是一個模型提出、驗證、運用的過程。這個世界會越來越由數據驅動,背後實際上就越來越是由模型驅動。如果一個PaaS或SaaS由外到裏都是模型驅動的,那它的定製能力一定很強,適應、生存、發展的能力也一定會很強,因爲不管需要什麼都可以直接用PaaS來生產,就像一個超級生產線,非常規範。

關於版本控制,在PaaS上定製的一切都可以看作配置,它們都需要版本控制能力,顆粒度可以由粗到細,當然這也要求爲用戶提供非生產環境,下面會提到。

4 環境

人都有可能犯錯,而改變就需要測試和驗證,雖然我們賦予了用戶定製的能力,但直接修改生產環境可能意味着不可恢復的風險。不論是SaaS還是PaaS,都顯然不妥。另外,用戶可能自己定製出很複雜的應用,而要用到它的新員工需要培訓,可是顯然不可能通過實際操作來進行培訓。因此,很有必要爲客戶提供非生產環境,這一點Salesforce做得非常到位,值得學習。這也是差異化利潤點,其各種環境的主要區別在於有沒有生產數據、有多少。

5 後臺進程組件

上圖中架構的主旨是爲了實現零編碼,該架構最終實現的PaaS的目標受衆是Citizen Developer,即沒有IT背景的人。也就是說後臺邏輯是完全由配置驅動的或者說聲明式的,並且要可視化地、以拖拽方式完成後臺邏輯的設計。雖然沒辦法說它能實現所有的後臺邏輯(因爲理論上邏輯是有無限可能的),但是,它所能做的範圍已經可以覆蓋絕大部分情況了。有人可能會說,後臺邏輯中的循環邏輯、分支邏輯怎麼辦呢?這也是可配置的。從技術上講,就如何滿足後臺的定製需求這一點來講,Salesforce有自己的編程語言Apex、自己的Query Language和Search Language,但個人覺得這都是面向程序員的,不夠好,本文建議零編碼,真正做到For Citizen Developer。

當一個請求經過網關到達一個服務進程以後,在這個進程裏發生的所有事都是由Process Engine總控的。其最爲核心的抽象是,輸入的對象、本地調用或者遠程調用返回的結果,或者本地子過程的處理結果都是有名稱的、可引用的、可以通過屬性路徑來操作的對象,而這個對象的結構是任意的,如圖中的input和result_*。概括起來講,就是內存裏的所有數據都是聲明方式可操作的。

從大的方面看,這個PaaS核心架構,有一種情況不能滿足,那就是微服務。如果客戶要求存儲獨立的微服務,那是做不到的,對客戶的系統設計能力要求相應地也比較高。其實微服務更多是給研發用的,客戶一般並不關心。對於一個租戶而言,微服務真正有意義的地方在於,業務所要求的數據處理能力已經超出了一個關係型數據庫實例的上限。這樣的話,可能更可取的方式是,看如何在一個租戶範圍內實現寫操作的分區(可以設計爲圖 14)。不過那就太大了,如果一個租戶都達到這樣一個系統要求的量級了,可能不應該找SaaS或PaaS供應商,而只能另覓他途了。

作爲SaaS或PaaS供應商,如果用微服務,可以考慮把人員組織機構、第三方服務的調用、報表等獨立出來,剩下的都是客戶的業務,在單體應用中處理即可。

協議建議採用HTTP2,它是多工(mutiplex)的,且服務端可推。即使內部使用,因爲HTTP2已經很快了,足夠用,簡單就是美。

再稍微提一下區塊鏈,區塊鏈最根本的地方是關於信任的,一般SaaS是關於企業內部活動的(intro-company),但是如果SaaS供應方把業務擴展到企業之間的行爲(inter-company),也許區塊鏈就有用武之地了,而入駐的企業就能變得既隔離又聯結。

審計,To B的應用相對於To C的應用往往是更嚴肅、更講究責任的,爲此,建議至少做到記錄級的審計,5W(who/where/when/what/how)。

權限,企業應用離不開權限管理,有沒有考慮到集團化的企業呢?多個分公司、子集團,各個分支機構之間在很多領域是相互隔離的,但也有可能是相通的。數據權限怎麼處理?能由集團的超級管理員來總控分公司的管理員嗎?支持阿米巴組織嗎?SaaS要走遠、要做大,諸如此類的問題恐怕是不可避免的,當然可以先放在低優先級去實現,但是在設計上必須支持纔好。

6 前端

寫到這裏,對於個性的滿足就剩前端了,這裏簡單給出建議:

  • 使用與後端相同的數據模型;
  • 封裝自己的控件,模型如下圖所示,有的時候共享dataset會讓有些事情處理起來變得很方便,頁面內有全局的dataset管理就更好了;

  • On demand,或者懶加載,需要了再請求,不要從後臺一次提取頁面可能需要的全量數據,其實很多情況下實際是在讓後臺做無用功;
  • 但凡用戶設置的,都在元數據的管理範圍之內,要讓滿足個性化需求這件事情完全由數據驅動的,不管是企業的個性還是用戶的個性;
  • 頁面內邏輯實現也可以是基於元數據的,也就是說頁面內的邏輯也是可定製的,即使實現起來有點複雜。

總結

本文的核心是聚焦於SaaS如何滿足個性化需求,由此引出PaaS,並不是定位於成爲PaaS Vendor,後者可能還需要擴展到數據倉庫、實時數據倉庫、流式計算、機器學習、數據中臺、數據應用、圖計算、IoT等方面。不過這些除了選擇合適的中間件,在平臺中實現連接件,剩下的用戶通過自服務實現所需定製構件的方法與文中提到的沒有很大差異,換句話說,僅爲量變。假設定位爲PaaS Vendor,本文分享的方法也是適用的,每個擴展領域只是商業上值不值的問題。

不過,如果邊界劃到滿足SaaS的需要,可以擴展到由用戶決定要不要微服務、要不要獨立的報表服務(包括獨立的庫)兩個方面。再想提一點的是,做SaaS,一定要做好與客戶既有系統、或可能的外在系統的集成,這對於SaaS供應商而言意味着數據雙向的流動。

另外,要讓系統合規,例如:GDPR規範,國家標準或行業標準,尤其是數據治理、安全方面,雖然本文已經建議做到記錄級的審計,但還是需要認真研究一下有關標準。

最後想跟大家分享幾條架構心得,這些也是筆者在寫本文的過程中考慮到的一些思想,雖然和SaaS沒有直接聯繫,但假如實踐中真的能夠以如下思想爲綱,必有受益。以下內容不成體系,想哪寫哪,希望對大家在思考具體問題的時候能有幫助。

  • Solve the business problem,不要片面地停留在技術層面,業務戰略、業務架構、業務發展訴求的滿足等業務層面的認知與探究纔是第一位的,要以業務爲始、以業務爲終;
  • One place, once for all,最好能夠在一個地方、一次性地解決一類問題,而不是頭疼醫頭腳疼醫腳,這是衡量一個架構好壞的準繩之一;
  • 站在巨人肩膀上,先學習人家是怎麼做的,驗證是否效果最好,擯棄權威思維定式;
  • 不是功能有了,就一切都有了,那樣到後來很可能就跑不動了。要動手做基礎研究,切忌跟風,一定要根據業務自己動腦子思考,心裏明白真正要什麼,往往真正要的不是框架本身,跑得快、可能欠下很多債,乃至積重難返。火車啓動慢,一旦跑起來其能量不是任何摩托車可比的,就像下圍棋一樣,局布得不好,遲早會爲其買單;
  • 業務、業務、抽象、抽象,抽象(abstract)這個詞來源於古希臘,意思是去掉細節。不要一開始就太糾結於具體技術、框架,如果思維的焦點大部分都是這些東西,作爲架構師是徹底把方向搞反了,其實務虛比務實更重要,如果事情已經推進到了涉及具體技術的階段,那已經不是大問題了。這並不是說不主張get your hands dirty on something,而是講什麼更重要、什麼是先導、什麼服從於什麼,這也是爲什麼一個高端的崗位更需要一個更注重修爲、有思想的人;
  • 早先大家用黑白照相機,然後有了彩色相機,現在用手機似乎就可以拍出不錯的照片,可是照的好的還是攝影師。這是一個類比,隨着技術生態的發展,各種框架不斷涌現,就好比是傻瓜相機,但做架構不是去學會如何按那個快門,不是去拼盤、攢框架,如果僅僅是那樣,就不是玩技術了,而是被技術玩了。可能有不少人以技藝自居,捨本逐末,不練思維,爲技而動,這是做不好架構的。現在網絡如此發達,知識唾手可得,就具體技術而言,不知、不會其實都不是太大的問題,真正的問題是如何全面、透徹地思考業務,然後在純抽象的層面明確地定義到底要什麼、具體的架構目標是什麼,然後才進入到技術選型階段。架構相對於開發是一個謀大於動的工作,做軟件不是人越多越好、越強,而是要想着如何用最少的人做更大的事;
  • 做一個強大的PaaS,完全可以僱一些類似富士康生產線上的人,經過完整培訓,然後就可以高效、高質量地生產包括SaaS在內的大部分軟件了,即使需要承受很大的併發、覆蓋複雜的業務邏輯。國內製造業的核心、高端技術,放眼望去,其實挺貧瘠的,軟件業更是如此。其實軟件的品控遠遠沒有製造業做得好,原因在於最終交付物中個人因素太多了,越多越不可控,而PaaS大大限制了開發者的自由裁量權,而且內在邏輯完全是可控的,因此質量一定比通常的開發模式高許多,且會累積性地提高,開發者不是質量的變量,這要求不只是低代碼(Low Code),而是零代碼(Zero Code);
  • 意識,人們常說要有某種意識,對於架構而言,要加怎樣的定語呢?建議:業務、客戶、服務、體驗、效率、成本、風險。架構工作的起點是業務的現狀(baseline),然後要擴展到業務發展目標(target)、系統現狀、團隊現狀,再到系統目標、整個信息化數字化的目標,這樣纔可能有清晰的架構發展路線圖與里程碑,而這些意識要貫徹到整個過程中。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章