2021-03-09 分類: 網(wǎng)站建設(shè)
在分布式程序架構(gòu)中,如果我們需要整個體系有更高的穩(wěn)定性,能夠?qū)M(jìn)程容災(zāi)或者動態(tài)擴(kuò)容提供支持,那么最難解決的問題,就是每個進(jìn)程中的內(nèi)存狀態(tài)。因為進(jìn)程一旦毀滅,內(nèi)存中的狀態(tài)會消失,這就很難不影響提供的服務(wù)。所以我們需要一種方法,讓進(jìn)程的內(nèi)存狀態(tài),不太影響整體服務(wù),甚至最好能變成“無狀態(tài)”的服務(wù)。當(dāng)然“狀態(tài)”如果不寫入磁盤,始終還是需要某些進(jìn)程來承載的。這個也是今天分享的主題--分布式緩存。
在現(xiàn)在流行的WEB開發(fā)模式中,很多人會使用PHP+Memcached+MySQL這種模型,在這里,PHP就是無狀態(tài)的,因為狀態(tài)都是放在Memcached里面。這種做法對于PHP來說,是可以隨時動態(tài)的毀滅或者新建,但是Memcached進(jìn)程就要保證穩(wěn)定才行;而且Memcached作為一個額外的進(jìn)程,和它通信本身也會消耗更多的延遲時間。因此我們需要一種更靈活和通用的進(jìn)程狀態(tài)保存方案,我們把這種任務(wù)叫做“分布式緩存”的策略。我們希望進(jìn)程在讀取數(shù)據(jù)的時候,能有高的性能,最好能和在堆內(nèi)存中讀寫類似,又希望這些緩存數(shù)據(jù),能被放在多個進(jìn)程內(nèi),以分布式的形態(tài)提供高吞吐的服務(wù),其中最關(guān)鍵的問題,就是緩存數(shù)據(jù)的同步。
PHP常用Memached做緩存
為了解決這個問題,下面一步步來分解這個問題:
1、哈希表
首先緩存應(yīng)該是某種特定形式的對象,而不應(yīng)該是任意類型的變量。因為需要對這些緩存進(jìn)行標(biāo)準(zhǔn)化的管理,盡管C++語言提供了運(yùn)算重載,可以對“=”號的寫變量操作進(jìn)行重新定義,但是現(xiàn)在基本沒有人推薦去做這樣的事。而哈希表剛好適合緩存這種概念的使用。
所有的哈希表(或者是Map接口),都是把數(shù)據(jù)的存放,分為key和value兩個部分,我們可以把想要緩存的數(shù)據(jù),作為value存放到“表”當(dāng)中,同時我們也可以用key把對應(yīng)的數(shù)據(jù)取出來,而“表”對象就代表了緩存。
2、讓“表”在多個進(jìn)程中都存在
其次需要讓這個“表”能在多個進(jìn)程中都存在。如果每個進(jìn)程中的數(shù)據(jù)都毫無關(guān)聯(lián),那問題其實就非常簡單,但是如果從A進(jìn)程把數(shù)據(jù)寫入緩存,然后在B進(jìn)程把數(shù)據(jù)讀取出來,那么就比較復(fù)雜了。總之“表”要有能把數(shù)據(jù)在A、B兩個進(jìn)程間同步的能力。因此一般會用三種策略:租約清理、租約轉(zhuǎn)發(fā)、修改廣播。
租約清理,一般是指,我們把存放某個key的緩存的進(jìn)程,稱為持有這個key的數(shù)據(jù)的“租約”,這個租約要登記到一個所有進(jìn)程都能訪問到的地方,比如是ZooKeeper集群進(jìn)程。那么在讀、寫發(fā)生的時候,如果本進(jìn)程沒有對應(yīng)的緩存,就先去查詢一下對應(yīng)的租約,如果被其他進(jìn)程持有,則通知對方“清理”,所謂“清理”,往往是指刪除用來讀的數(shù)據(jù),回寫用來寫的數(shù)據(jù)到數(shù)據(jù)庫等持久化設(shè)備,等清理完成后,在進(jìn)行正常的讀寫操作,這些操作可能會重新在新的進(jìn)程上建立緩存。這種策略在緩存命中率比較高的情況下,性能是最好的,因為一般無需查詢租約情況,就可以直接操作;但如果緩存命中率低,那么就會出現(xiàn)緩存反復(fù)在不同進(jìn)程間“移動”,會嚴(yán)重降低系統(tǒng)的處理性能。
一般把存放某個KEY的緩存的進(jìn)程,稱為持有這個KEY數(shù)據(jù)的“租約”,同時也要登記到集群的共享數(shù)據(jù)進(jìn)程中。和上面租約清理不同的地方在于,如果發(fā)現(xiàn)持有租約的進(jìn)程不是本次操作的進(jìn)程,就會把整個數(shù)據(jù)的讀、寫請求,都通過網(wǎng)絡(luò)“轉(zhuǎn)發(fā)”個持有租約的進(jìn)程,然后等待他的操作結(jié)果返回。這種做法由于每次操作都需要查詢租約,所以性能會稍微低一些;但如果緩存命中率不高,這種做法能把緩存的操作分擔(dān)到多個進(jìn)程上,而且也無需清理緩存,這比租約清理的策略適應(yīng)性更好。
上面兩種策略,都需要維護(hù)一份緩存數(shù)據(jù)的租約,但是本身對于租約的操作,就是一種比較耗費(fèi)性能的事情。所以有時候可以采用一些更簡單,但可能承受一些不一致性的策略:對于讀操作,每個節(jié)點(diǎn)的讀都建立緩存,每次讀都判斷是否超過預(yù)設(shè)的讀冷卻時間x,超過則清理緩存從持久化重建;對于寫操作,每個節(jié)點(diǎn)上都判斷是否超過預(yù)設(shè)的寫冷卻時間y,超過則展開清理操作。
清理操作也分兩種,如果數(shù)據(jù)量小就廣播修改數(shù)據(jù);如果數(shù)據(jù)量大就廣播清理通知回寫到持久化中。這樣雖然可能會有一定的不一致風(fēng)險,但是如果數(shù)據(jù)不是那種要求太高的,而且緩存命中率又能比較有保障的話(比如根據(jù)KEY來進(jìn)行一致性哈希訪問緩存進(jìn)程),那么真正因為寫操作廣播不及時,導(dǎo)致數(shù)據(jù)不一致的情況還是會比較少的。這種策略實現(xiàn)起來非常簡單,無需一個中心節(jié)點(diǎn)進(jìn)程維護(hù)數(shù)據(jù)租約,也無需復(fù)雜的判斷邏輯進(jìn)行同步,只要有廣播的能力,加上對于寫操作的一些配置,就能實現(xiàn)高效的緩存服務(wù)。
所以“修改廣播”策略是在大多數(shù)需要實時同步,但數(shù)據(jù)一致性要求不高的領(lǐng)域最常見的手段。著名的DNS系統(tǒng)的緩存就是接近這種策略:我們要修改某個域名對應(yīng)的IP,并不是立刻在全球所有的DNS服務(wù)器上生效,而是需要一定時間廣播修改給其他服務(wù)區(qū)。而我們每個DSN服務(wù)器,都具備了大量的其他域名的緩存數(shù)據(jù)。
在高性能的服務(wù)器架構(gòu)中,常用的緩存和分布兩種策略,往往是結(jié)合到一起使用的。雖然這兩種策略,都有無數(shù)種不同的表現(xiàn)形式,成為各種各樣的技術(shù)流派,但是只有清楚的理解這些技術(shù)的原理,并且和實際的業(yè)務(wù)場景結(jié)合起來,才能真正的做出滿足應(yīng)用要求的高性能架構(gòu)。
當(dāng)前標(biāo)題:詳解服務(wù)器框架中的分布式緩存
文章地址:http://jinyejixie.com/news0/104900.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供商城網(wǎng)站、網(wǎng)頁設(shè)計公司、企業(yè)網(wǎng)站制作、App開發(fā)、全網(wǎng)營銷推廣、網(wǎng)站收錄
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容