溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

分布式系統(tǒng)關(guān)注點(diǎn)—“無狀態(tài)”詳解

發(fā)布時(shí)間:2020-06-24 16:05:23 來源:網(wǎng)絡(luò) 閱讀:246 作者:UMUTech 欄目:開發(fā)技術(shù)

一、初識“狀態(tài)”
我們首先舉個(gè)例子。

開發(fā) Z 哥對運(yùn)維 Y 弟喊:“Y 弟,現(xiàn)在系統(tǒng)好卡,剛上了一波活動(dòng),趕緊幫我加幾臺機(jī)器上去頂一下?!?/p>

Y 弟回復(fù)說:“沒問題,分分鐘搞定”。

然后就發(fā)現(xiàn)數(shù)據(jù)庫的壓力迅速上升,DBA 就吼了:“Z 哥,你丫的搞什么呢?數(shù)據(jù)庫要被你弄垮了”。

然后客服那邊接框也爆炸了,越來越多的用戶說剛登陸后沒多久,操作著就退出了,接著登陸,又退出了,到底還做不做生意了。

這個(gè)案例中的問題,產(chǎn)生的根本原因是因?yàn)橄到y(tǒng)中存在著大量“有狀態(tài)”的業(yè)務(wù)處理過程。

二、“有狀態(tài)”和“無狀態(tài)”
N.Wirth 曾經(jīng)在它 1984 年出版的書中將程序的定義經(jīng)典的概括為:程序 = 數(shù)據(jù)結(jié)構(gòu) + 算法。(這個(gè)概括也是這本書的書名)

這是一個(gè)很有意思的啟發(fā),受它的影響,z 哥認(rèn)為程序做的事情本質(zhì)就是“數(shù)據(jù)的移動(dòng)和組合”,以此來達(dá)到我們所期望的結(jié)果。而如何移動(dòng)、如何組合是由“算法”來定的,所以 z 哥延伸出一個(gè)新的定義:數(shù)據(jù) + 算法 = 成果。

通過程序處理所得到的“成果”其實(shí)和你平時(shí)生活中完成的任何事情所得到的“成果”是一樣的。任何一個(gè)“成果”都是你通過一系列的“行動(dòng)”將最開始的“原料”進(jìn)行加工、轉(zhuǎn)化,最終得到你所期望的“成果”。

比如,你將常溫的水,通過“倒入水壺”、“通電加熱”等工作后變成了 100 度的水,就是這樣一個(gè)過程。

正如燒水的例子,大多數(shù)時(shí)候得到一個(gè)“成果”往往需要好幾道“行動(dòng)”才能完成。

這個(gè)時(shí)候如果想降低這幾道“行動(dòng)”總的成本(如:時(shí)間)該怎么辦呢?

自然就是提煉出反復(fù)要做的事情,讓其只做一次。而這個(gè)事情在程序中,就是將一部分“數(shù)據(jù)”放到一個(gè)“暫存區(qū)”(一般就是本地內(nèi)存),以提供給相關(guān)的“行動(dòng)”共用。

但是如此一來,就導(dǎo)致了需要增加一道關(guān)系,以表示每一個(gè)“行動(dòng)”與哪一個(gè)“暫存區(qū)”關(guān)聯(lián)。因?yàn)樵诔绦蚶?,“行?dòng)”可能是“多線程”的。

這時(shí),這個(gè)“行動(dòng)”就變成“有狀態(tài)”的了。

題外話:共用同一個(gè)“暫存區(qū)”的多個(gè)“行動(dòng)”所處的環(huán)境經(jīng)常被稱作“上下文”。

我們再來深入聊聊“有狀態(tài)”。

“暫存區(qū)”里存的是“數(shù)據(jù)”,所以可以理解為“有數(shù)據(jù)”就等價(jià)于“有狀態(tài)”。

“數(shù)據(jù)”在程序中的作用范圍分為“局部”和“全局”(對應(yīng)局部變量和全局變量),因此“狀態(tài)”其實(shí)也可以分為兩種,一種是局部的“會(huì)話狀態(tài)”,一種是全局的“資源狀態(tài)”。

題外話:因?yàn)橛行┓?wù)端不單單負(fù)責(zé)運(yùn)算,還會(huì)提供其自身范圍內(nèi)的“數(shù)據(jù)”出去,這些“數(shù)據(jù)”屬于服務(wù)端完整的一部分,被稱作“資源”。所以,理論上資源可以被每個(gè)會(huì)話來使用,因此是全局的狀態(tài)。

本文聊的“有狀態(tài)”都指的是“會(huì)話狀態(tài)”。

與“有狀態(tài)”相反的是“無狀態(tài)”,“無狀態(tài)”意味著每次“加工”的所需的“原料”全部由外界提供,服務(wù)端內(nèi)部不做任何的“暫存區(qū)”。并且請求可以提交到服務(wù)端的任意副本節(jié)點(diǎn)上,處理結(jié)果都是完全一樣的。

有一類方法天生是“無狀態(tài)”,就是負(fù)責(zé)表達(dá)移動(dòng)和組合的“算法”。因?yàn)樗谋举|(zhì)就是:

接收“原料”(入?yún)ⅲ?br/>“加工”并返回“成果”(出參)

為什么網(wǎng)上主流的觀點(diǎn)都在說要將方法多做成“無狀態(tài)”的呢?

因?yàn)槲覀兏?xí)慣于編寫“有狀態(tài)”的代碼,但是“有狀態(tài)”不利于系統(tǒng)的易伸縮性和可維護(hù)性。

在分布式系統(tǒng)中,“有狀態(tài)”意味著一個(gè)用戶的請求必須被提交到保存有其相關(guān)狀態(tài)信息的服務(wù)器上,否則這些請求可能無法被理解,導(dǎo)致服務(wù)器端無法對用戶請求進(jìn)行自由調(diào)度(例如雙 11 的時(shí)候臨時(shí)加再多的機(jī)器都沒用)。

同時(shí)也導(dǎo)致了容錯(cuò)性不好,倘若保有用戶信息的服務(wù)器宕機(jī),那么該用戶最近的所有交互操作將無法被透明地移送至備用服務(wù)器上,除非該服務(wù)器時(shí)刻與主服務(wù)器同步全部用戶的狀態(tài)信息。

但是如果想獲得更好的伸縮性,就需要盡量將“有狀態(tài)”的處理機(jī)制改造成“無狀態(tài)”的處理機(jī)制。
三、“無狀態(tài)”化處理
將“有狀態(tài)”的處理過程改造成“無狀態(tài)”的,思路比較簡單,內(nèi)容不多。

首先,狀態(tài)信息前置,豐富入?yún)?,將處理需要的?shù)據(jù)盡可能都通過上游的客戶端放到入?yún)⒅袀鬟^來。

當(dāng)然,這個(gè)方案的弊端也很明顯:網(wǎng)絡(luò)數(shù)據(jù)包的大小會(huì)更大一些。

另外,客戶端與服務(wù)端的交互中如果涉及到多次交互,則需要來回傳遞后續(xù)服務(wù)端處理中所需的數(shù)據(jù),以避免需要在服務(wù)端暫存。

(橙色請求,綠色響應(yīng))

這些改造的目的都是為了盡量少出現(xiàn)類似下面的代碼。

func(){
returni++;
}

而是變成:

func(i){
returni+1;
}

要更好的做好這個(gè)“無狀態(tài)”化的工作,依賴于你在架構(gòu)設(shè)計(jì)或者項(xiàng)目設(shè)計(jì)中的合理分層。

盡量將會(huì)話狀態(tài)相關(guān)的處理上浮到最前面的層,因?yàn)橹挥凶钋懊娴膶硬排c系統(tǒng)使用者接觸,如此一來,其它的下層就可以將“無狀態(tài)”作為一個(gè)普遍性的標(biāo)準(zhǔn)去做。

與此同時(shí),由于會(huì)話狀態(tài)集中在最前面的層,所以哪怕真的狀態(tài)丟失了,重建狀態(tài)的成本相對也小很多。

比如三層架構(gòu)的話,保證 BLL 和 DAL 都不要有狀態(tài),代碼的可維護(hù)性大大提高。

如果是分布式系統(tǒng)的話,保證那些被服務(wù)化的程序都不要有狀態(tài)。除了能提高可維護(hù)性,也大大有利于做灰度發(fā)布、A/B 測試。

題外話:在這里,提到做分層的目的是為了說明,只有將 IO 密集型程序和 CPU 密集型程序分離,才是通往“無狀態(tài)”真正的出路。一旦分離后,CPU 密集型的程序自然就是“無狀態(tài)”了。

如此也能更好的做“彈性擴(kuò)容”。因?yàn)槌R姷男枰皬椥詳U(kuò)容”的場景一般指的就是 CPU 負(fù)荷過大的時(shí)候。

最后,如果前面的都不合適,可以將共享存儲(chǔ)作為降級預(yù)案來運(yùn)用,如遠(yuǎn)程緩存、數(shù)據(jù)庫等。然后當(dāng)狀態(tài)丟失的時(shí)候可以從這些共享存儲(chǔ)中恢復(fù)。

所以,最理想的狀態(tài)存放點(diǎn)。要么在最前端,要么在最底層的存儲(chǔ)層。

四、總結(jié)
任何事物都是有兩面性的,正如前面提到的,我們并不是要所有的業(yè)務(wù)處理都改造成“無狀態(tài)”,而只是挑其中的一部分。最終還是看“價(jià)值”,看“性價(jià)比”。

比如,將一個(gè)以“狀態(tài)”為核心的即時(shí)聊天工具的所有處理過程都改造成“無狀態(tài)”的,就有點(diǎn)得不償失了。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI