面試官:為什么每個(gè)微服務(wù)都要有自己獨(dú)立的數(shù)據(jù)庫(kù)?
這個(gè)問(wèn)題是我在知乎上看到的,答案并不是一邊倒,還是存在爭(zhēng)議性的。
其中,一些持反方觀點(diǎn)同學(xué)的理由如下:
(1)從硬件成本和維護(hù)成本上看,反而應(yīng)該多個(gè)微服務(wù)盡可能地共用中間件和數(shù)據(jù)庫(kù)。
(2)微服務(wù)的獨(dú)立數(shù)據(jù)庫(kù)是指邏輯獨(dú)立,而不是物理獨(dú)立,在物理層面上是可以共用數(shù)據(jù)庫(kù)的。
btw:有點(diǎn)兒像《非誠(chéng)勿擾》中葛優(yōu)對(duì)舒淇說(shuō)的話:“那你能允許我心在你這,身體上開點(diǎn)兒小差嗎”?
(3)你把數(shù)據(jù)庫(kù)也看做一個(gè)微服務(wù)就好理解了,微服務(wù)之間本身就是多對(duì)多的關(guān)系,公用有何不可呢?
拋出我的觀點(diǎn)吧,我完全支持每個(gè)微服務(wù)都要有自己獨(dú)立的數(shù)據(jù)庫(kù),但每個(gè)數(shù)據(jù)庫(kù)是否使用獨(dú)立的服務(wù)器,這個(gè)需要視業(yè)務(wù)情況而定。
具體原因請(qǐng)見(jiàn)下圖:
圖片
系統(tǒng)可用性
說(shuō)說(shuō)我當(dāng)年的情況吧,當(dāng)時(shí)我在一個(gè)在線教育公司,該公司早期的系統(tǒng)是一個(gè)單體架構(gòu),一個(gè)大的后端工程,并對(duì)應(yīng)一個(gè)大的數(shù)據(jù)庫(kù)。
后來(lái)人越招越多,業(yè)務(wù)也越來(lái)越復(fù)雜,幾十人的研發(fā)團(tuán)隊(duì)共同在一個(gè)大的單體服務(wù)中進(jìn)行開發(fā),這是明顯不現(xiàn)實(shí)的。
于是,研發(fā)團(tuán)隊(duì)便按照組織結(jié)構(gòu)進(jìn)行服務(wù)拆分,將那個(gè)大的單體服務(wù)拆分為學(xué)生端服務(wù)、教師端服務(wù)、管理端服務(wù)和銷售端服務(wù)。
圖片
隨后,我們的學(xué)生端服務(wù)又按照業(yè)務(wù)領(lǐng)域,拆分出來(lái)了學(xué)生課表、積分商城和學(xué)生運(yùn)營(yíng)活動(dòng)服務(wù)。
其中,學(xué)生課表服務(wù)的重要等級(jí)是P0(最重要的),因?yàn)閷W(xué)生是以課表為入口進(jìn)入教室上課的,也就是說(shuō),如果課表服務(wù)掛了就會(huì)導(dǎo)致無(wú)法上課,會(huì)給公司帶來(lái)重大經(jīng)濟(jì)損失。
積分商城服務(wù),是學(xué)生通過(guò)積分兌換學(xué)習(xí)用品的,如果服務(wù)掛了會(huì)影響用戶體驗(yàn),但不會(huì)造成經(jīng)濟(jì)損失,因此重要等級(jí)為P1。
而運(yùn)營(yíng)活動(dòng)服務(wù)的主要功能為,公司的運(yùn)營(yíng)人員會(huì)創(chuàng)建一些活動(dòng)來(lái)增加學(xué)生在平臺(tái)上的活躍度,比如:學(xué)生將自己創(chuàng)作的作品,發(fā)到朋友圈中收集點(diǎn)贊,被點(diǎn)贊最多的學(xué)生獲得小禮品,等等。
但當(dāng)時(shí)的情況是,學(xué)生課表、積分商城和學(xué)生運(yùn)營(yíng)活動(dòng)這三個(gè)服務(wù)拆出來(lái)了,還是共用了一個(gè)學(xué)生端的數(shù)據(jù)庫(kù)。
有一天晚上,正好是學(xué)生上課的高峰期,忽然收到一通報(bào)警,學(xué)生端數(shù)據(jù)庫(kù)的負(fù)載竟然達(dá)到了200多,CPU使用率也被干到了100%。
緊接著,公司的大群中就有好幾個(gè)業(yè)務(wù)同事發(fā)消息說(shuō),學(xué)生投訴說(shuō)課表看不到了,不能進(jìn)入教室上課了。
我們聽了之后,趕緊登錄監(jiān)控系統(tǒng)去查看學(xué)生課表服務(wù)的相關(guān)接口,發(fā)現(xiàn)由于不顯示課表學(xué)生反復(fù)刷新頁(yè)面的原因,接口的QPS確實(shí)比正常情況下高了好幾倍,但都被Sentinel限流掉了,不應(yīng)該造成影響才對(duì)。
正在一籌莫展之際,我忽然發(fā)現(xiàn)在監(jiān)控系統(tǒng)上,學(xué)生運(yùn)營(yíng)活動(dòng)服務(wù)的接口QPS和TPS同樣高得離譜,比平時(shí)高十幾倍,且彪高的起始時(shí)間要比學(xué)生課表接口早一兩分鐘。
這就證明了,很大可能是學(xué)生運(yùn)營(yíng)活動(dòng)服務(wù)的流量彪高,且學(xué)生運(yùn)營(yíng)活動(dòng)服務(wù)上的接口沒(méi)有做限流保護(hù),造成了服務(wù)共用的學(xué)生端數(shù)據(jù)庫(kù)扛不住了,從而影響了學(xué)生課表服務(wù)。
圖片
于是,我們趕緊啟動(dòng)降級(jí)機(jī)制,關(guān)閉了所有的學(xué)生運(yùn)營(yíng)活動(dòng)服務(wù)的接口。沒(méi)過(guò)一會(huì)兒,學(xué)生課表可以正常訪問(wèn)了。
接下來(lái),我們和DBA連夜把學(xué)生課表服務(wù)所對(duì)應(yīng)的數(shù)據(jù)表單獨(dú)拆分出來(lái),遷移到一個(gè)新的數(shù)據(jù)庫(kù)服務(wù)器上進(jìn)行獨(dú)享。
嗯,重要等級(jí)高的微服務(wù)不但要有自己獨(dú)立的數(shù)據(jù)庫(kù),且必須是獨(dú)立的數(shù)據(jù)庫(kù)服務(wù)器,通過(guò)鏈路隔離的方式提升系統(tǒng)可用性。
當(dāng)然,一些重要等級(jí)不高的服務(wù)獨(dú)立數(shù)據(jù)庫(kù)即可,并不需要獨(dú)立數(shù)據(jù)庫(kù)服務(wù)器,這樣可以節(jié)省硬件成本。
架構(gòu)貫徹性
我們都知道,微服務(wù)架構(gòu)之間是通過(guò)RPC調(diào)用來(lái)進(jìn)行業(yè)務(wù)串聯(lián)的。
以常見(jiàn)的電商場(chǎng)景舉例,需要給用戶展示他所購(gòu)買的訂單列表,此時(shí)訂單中心會(huì)調(diào)用商品中心的API獲取商品數(shù)據(jù),然后再跟訂單數(shù)據(jù)進(jìn)行merge,返回給前端用戶。
如果此時(shí)商品中心和訂單中心所對(duì)應(yīng)的數(shù)據(jù)表放在一個(gè)數(shù)據(jù)庫(kù)中,可以預(yù)見(jiàn)的情況就是,研發(fā)人員會(huì)把訂單表和商品表進(jìn)行多表關(guān)聯(lián)的方式來(lái)代替RPC調(diào)用+ 數(shù)據(jù)merge,因?yàn)檫@樣做非常省事。
如下圖所示:
而一旦破了這個(gè)口子,就會(huì)形成“破窗效應(yīng)”,系統(tǒng)架構(gòu)就變成分布式單體架構(gòu)。
有人說(shuō),可以靠口頭約束的方式來(lái)規(guī)避這種情況,我并不認(rèn)同。
想象一種場(chǎng)景,如果一個(gè)同學(xué)趕項(xiàng)目工期,半夜12點(diǎn)還在那挑燈夜戰(zhàn)呢。此時(shí),如果有一種方式讓他快速寫完代碼回家睡覺(jué),他會(huì)毫不動(dòng)心一絲不茍地“按照規(guī)律辦事”?
研發(fā)效率
微服務(wù)獨(dú)立數(shù)據(jù)庫(kù)的另一個(gè)好處就是,讀寫入口收斂,這樣是可以提升研發(fā)效率的。
舉個(gè)例子,如果我們把商品表進(jìn)行垂直拆分,拆分成商品表 + 商品詳情表,如果按照標(biāo)準(zhǔn)的獨(dú)立數(shù)據(jù)庫(kù)方式,只需要商品中心來(lái)進(jìn)行對(duì)應(yīng)的代碼變更就可以了,這對(duì)依賴商品中心的其他服務(wù)來(lái)講是透明的。
而非獨(dú)立庫(kù)模式就比較蛋疼了,每個(gè)去直接查詢商品表的服務(wù)都需要改一遍。
如下圖所示:
圖片
上述例子屬于讀入口收斂的范疇,而寫入口不收斂,在多個(gè)服務(wù)中對(duì)一張數(shù)據(jù)表進(jìn)行寫入的話,則帶來(lái)的問(wèn)題同樣不少。
問(wèn)題包括:
(1)表結(jié)構(gòu)變更問(wèn)題,如果增加一個(gè)非空字段,那么所有寫入口的代碼全部需要變更,且這種“散彈式”修改非常容易遺漏。
(2)問(wèn)題排查難,一旦發(fā)現(xiàn)寫入了問(wèn)題數(shù)據(jù),那各個(gè)寫入口全部需要進(jìn)行排查,工作量大且復(fù)雜。
除了讀寫入口收斂問(wèn)題,再有就是,如果形成了上文中所說(shuō)的“分布式單體架構(gòu)”,那接下來(lái)再想進(jìn)行優(yōu)化改善的話,將會(huì)是一件工作量極大的事情,所以不如一次做好。
結(jié)語(yǔ)
綜上所述,我認(rèn)為如果選擇了微服務(wù)架構(gòu),那每個(gè)微服務(wù)獨(dú)立數(shù)據(jù)庫(kù)完全是個(gè)必選項(xiàng),獨(dú)立數(shù)據(jù)庫(kù)服務(wù)器則是個(gè)可選項(xiàng),需要兼顧可用性和硬件成本。