微服務(wù)真的不挑數(shù)據(jù)庫嗎?如何選擇?
微服務(wù)架構(gòu)的應(yīng)用具有很好的擴展性,因此似乎微服務(wù)并不挑數(shù)據(jù)庫,在微服務(wù)中使用哪種數(shù)據(jù)庫問題都不是很大。事實真的如此嗎?也許對于一些研發(fā)能力很強的隊伍來說,為微服務(wù)選擇數(shù)據(jù)庫是很容易的事情,因為選擇的數(shù)據(jù)庫無論存在哪方面的缺陷,他們都有辦法通過應(yīng)用方面的優(yōu)化去解決它。而對于一些普通的研發(fā)隊伍來說,有時候還真的搞不定。
很多企業(yè)剛剛轉(zhuǎn)向微服務(wù)架構(gòu)的時候也是交了大量的學(xué)費的,很多企業(yè)的微服務(wù)架構(gòu)轉(zhuǎn)型是:“開發(fā)一時爽,運維兩眼淚”。實際上很多設(shè)計和開發(fā)的缺陷最后都是讓運維來想辦法填坑的。與傳統(tǒng)的集中架構(gòu)不同,微服務(wù)的坑,運維填起來難度大多了。如果微服務(wù)應(yīng)用將一個大數(shù)據(jù)庫拆分成多個小型的領(lǐng)域數(shù)據(jù)庫,那么一條重要的原則就是要永遠確保這些數(shù)據(jù)庫是小型數(shù)據(jù)庫,其數(shù)據(jù)量的增長是緩慢的,隨著每年業(yè)務(wù)的增長率稍微增長一點點的,歷史數(shù)據(jù)一定是能夠及時歸檔的。這樣的小型數(shù)據(jù)庫才會在長期運行的時間里保證較好的性能,不會給運維人員帶來太大的負擔(dān)。
從另外一個角度來講,微服務(wù)的數(shù)據(jù)應(yīng)該存儲到適當(dāng)?shù)臄?shù)據(jù)庫中,而不是在沒有掌握數(shù)據(jù)存取特點的情況下,隨意選擇一個數(shù)據(jù)庫。目前數(shù)據(jù)庫可選擇的種類太多了,以阿里云等云廠商為例,他們就已經(jīng)為微服務(wù)開發(fā)者提供了眼花繚亂的選項。
不同的應(yīng)用場景選擇不同的數(shù)據(jù)庫產(chǎn)品,才能讓項目今后的發(fā)展路徑更為順暢。這么多的數(shù)據(jù)庫產(chǎn)品,我們該如何來選擇呢?雖然微應(yīng)用已經(jīng)弱化了數(shù)據(jù)庫的很多特性,大大減少了跨服務(wù)的數(shù)據(jù)融合計算,不過針對不同類型的微服務(wù),我們?nèi)匀恍枰种?jǐn)慎的來選擇數(shù)據(jù)庫產(chǎn)品。
我們該如何為自己的微服務(wù)選擇適當(dāng)?shù)臄?shù)據(jù)庫產(chǎn)品呢?這就需要從幾個方面去考慮了。
首先要考慮的是你的微服務(wù)中對數(shù)據(jù)的訪問方式。選擇數(shù)據(jù)庫的最重要的因素是你的查詢的模式是什么樣的。如果你只需要存儲某些鍵值,那么KV數(shù)據(jù)庫可能是比較好的選擇,比如你可以選擇Redis;如果你的應(yīng)用基本上都是基于主鍵查詢,附加一些主鍵關(guān)聯(lián)的其他字段,那么一些寬列數(shù)據(jù)庫可能很適合你的微服務(wù),比如Cassandra;如果你的應(yīng)用主要是訪問一些單表中的數(shù)據(jù),不過檢索條件可能會比較豐富,模式不是十分固定,那么使用文檔數(shù)據(jù)庫可能比較好,MongoDB、CouchDB等可能比較對你的胃口;如果你的應(yīng)用經(jīng)常有一些多表關(guān)聯(lián)的關(guān)系型訪問,那么關(guān)系型數(shù)據(jù)庫,比如PostgreSQL、MySQLl等可能更適合;如果你的應(yīng)用主要是根據(jù)主鍵做模糊查詢,全文檢索,那么ES可能會優(yōu)于其他數(shù)據(jù)庫。
如果有一個場景有多種數(shù)據(jù)庫適合,那么可以根據(jù)數(shù)據(jù)一致性等要求來做出進一步的篩選,比如你的場景中MySQL和MongoDB都比較適合,那么如果在要求強一致性的情況下,傾向于選擇MySQL,否則可以考慮MongoDB。
實際上,在你的應(yīng)用系統(tǒng)中,不同的微服務(wù)可以選擇不同類型的數(shù)據(jù)庫,從而最大限度的優(yōu)化數(shù)據(jù)訪問。比如你的有很多視頻要存儲,那么選擇S3對象存儲來存儲視頻肯定比把視頻存儲到關(guān)系型數(shù)據(jù)庫的LOB字段中要好得多,在關(guān)系型數(shù)據(jù)庫中只需要保存對象的ID就可以了。
在一個應(yīng)用系統(tǒng)中使用多種數(shù)據(jù)庫也不是多多益善,數(shù)據(jù)庫種類太多會導(dǎo)致系統(tǒng)架構(gòu)變得臃腫,運維的成本也會大大增加。因此適當(dāng)?shù)倪x擇幾種數(shù)據(jù)庫才是較好的設(shè)計方案。這種情況下,一些多模數(shù)據(jù)庫就比較具有優(yōu)勢了。比如說在系統(tǒng)中以RDBMS為主,稍微有一些JSON數(shù)據(jù)存儲、還有少量應(yīng)用會使用一些時序數(shù)據(jù)和一些GIS數(shù)據(jù),那么選擇PostgreSQL就可以滿足這些綜合要求。
實際上為微服務(wù)選擇數(shù)據(jù)庫產(chǎn)品不僅僅要考慮這些因素,開發(fā)團隊的經(jīng)驗、運維能力、成本等因素也是要考慮的。因為微服務(wù)架構(gòu)的特點,我們通過領(lǐng)域建模會將一個大型系統(tǒng)的數(shù)據(jù)拆分為多個不同的子領(lǐng)域,因此高并發(fā)支持能力,性能,大數(shù)據(jù)量下的復(fù)雜SQL性能等方面需要考慮的因素相對少一些。不過對于一些稍微極端一些的應(yīng)用場景,可能我們需要考慮的會更為復(fù)雜一些。
另外一點就是聚合計算的問題,任何應(yīng)用都有聚合計算的問題,特別是一些實時聚合計算的需求,我們也必須滿足。因此在領(lǐng)域建模將數(shù)據(jù)拆分之后我們依然需要將這些數(shù)據(jù)匯聚起來進行計算。雖然我們也可以使用ShardingSphere這樣的數(shù)據(jù)庫網(wǎng)關(guān)來實現(xiàn)一定的聚合計算,不過大數(shù)據(jù)量的分布式環(huán)境的聚合計算在性能上往往會遇到一些問題。解決此類問題的方法不外乎兩個,一個是在微服務(wù)層面,對明細數(shù)據(jù)進行準(zhǔn)實時匯總,這樣聚合計算不需要針對明細數(shù)據(jù)進行。另外一種方法就是使用ODS或者數(shù)據(jù)中臺作為聚合計算的平臺,從而減輕微服務(wù)數(shù)據(jù)層的負擔(dān)。
原本一個大型數(shù)據(jù)庫拆分為很多個小庫后會不會給運維帶來壓力呢?答案是肯定的,因此微服務(wù)的架構(gòu)師應(yīng)該對這些小型數(shù)據(jù)庫做一個很好的架構(gòu)設(shè)計,包括高可用、災(zāi)備,數(shù)據(jù)歸檔,數(shù)據(jù)自動清理,這些工作運維人員可以參與設(shè)計,但是必須在應(yīng)用中實現(xiàn)自動化的管理,否則這一堆堆的小庫上來,運維人員平時要是去監(jiān)控巡檢,平時也沒啥事,還浪費時間,一旦出了問題,還不太好處置。
如果你的應(yīng)用是托管在公有云上的,并且你的每個庫的容量、負載都可以比較好的控制,那么采購公有云的RDS是比較省事的做法,不過公有云的特點是入門很便宜,一旦你的庫變大了,服務(wù)要升級了,那么價錢絕對不是簡單的乘以某個倍數(shù)的問題。公有云上,大的主機和數(shù)據(jù)庫服務(wù)價格會有一個跳躍式的提升,應(yīng)用架構(gòu)師要十分注意這一點。私有云對費用相對沒有那么敏感,使用私有云的RDS服務(wù)可以大大的降低運維的壓力。在這方面,微服務(wù)的架構(gòu)師一定要先和云平臺部門做好溝通。
如果你不希望管理碎片化的小型數(shù)據(jù)庫(無論是RDS還是運行在容器中的數(shù)據(jù)庫),那么帶有多租戶、多模存儲能力的分布式數(shù)據(jù)庫也許是你喜歡的選擇。運維一個大型的云數(shù)據(jù)庫可能比運維幾十個小數(shù)據(jù)庫更合你的胃口。這種選擇也是合適的,只要和你的企業(yè)的整體IT政策與IT基礎(chǔ)架構(gòu)相吻合,那也是不錯的選擇。