高性能服务器架构思路(五)——分布式缓存
2019獨角獸企業重金招聘Python工程師標準>>>
?
版權聲明:本文由韓偉原創文章,轉載請注明出處:?
文章原文鏈接:https://www.qcloud.com/community/article/167
來源:騰云閣?https://www.qcloud.com/community
?
在分布式程序架構中,如果我們需要整個體系有更高的穩定性,能夠對進程容災或者動態擴容提供支持,那么最難解決的問題,就是每個進程中的內存狀態。因為進程一旦毀滅,內存中的狀態會消失,這就很難不影響提供的服務。所以我們需要一種方法,讓進程的內存狀態,不太影響整體服務,甚至最好能變成“無狀態”的服務。當然“狀態”如果不寫入磁盤,始終還是需要某些進程來承載的。在現在流行的WEB開發模式中,很多人會使用PHP+Memcached+MySQL這種模型,在這里,PHP就是無狀態的,因為狀態都是放在Memcached里面。這種做法對于PHP來說,是可以隨時動態的毀滅或者新建,但是Memcached進程就要保證穩定才行;而且Memcached作為一個額外的進程,和它通信本身也會消耗更多的延遲時間。因此我們需要一種更靈活和通用的進程狀態保存方案,我們把這種任務叫做“分布式緩存”的策略。我們希望進程在讀取數據的時候,能有最高的性能,最好能和在堆內存中讀寫類似,又希望這些緩存數據,能被放在多個進程內,以分布式的形態提供高吞吐的服務,其中最關鍵的問題,就是緩存數據的同步。
PHP常用Memached做緩存
為了解決這個問題,我們需要先一步步來分解這個問題:
首先,我們的緩存應該是某種特定形式的對象,而不應該是任意類型的變量。因為我們需要對這些緩存進行標準化的管理,盡管C++語言提供了運算重載,我們可以對“=”號的寫變量操作進行重新定義,但是現在基本已經沒有人推薦去做這樣的事。而我們手頭就有最常見的一種模型,適合緩存這種概念的使用,它就是——哈希表。所有的哈希表(或者是Map接口),都是把數據的存放,分為key和value兩個部分,我們可以把想要緩存的數據,作為value存放到“表”當中,同時我們也可以用key把對應的數據取出來,而“表”對象就代表了緩存。
其次我們需要讓這個“表”能在多個進程中都存在。如果每個進程中的數據都毫無關聯,那問題其實就非常簡單,但是如果我們可能從A進程把數據寫入緩存,然后在B進程把數據讀取出來,那么就比較復雜了。我們的“表”要有能把數據在A、B兩個進程間同步的能力。因此我們一般會用三種策略:租約清理、租約轉發、修改廣播
租約清理,一般是指,我們把存放某個key的緩存的進程,稱為持有這個key的數據的“租約”,這個租約要登記到一個所有進程都能訪問到的地方,比如是ZooKeeper集群進程。那么在讀、寫發生的時候,如果本進程沒有對應的緩存,就先去查詢一下對應的租約,如果被其他進程持有,則通知對方“清理”,所謂“清理”,往往是指刪除用來讀的數據,回寫用來寫的數據到數據庫等持久化設備,等清理完成后,在進行正常的讀寫操作,這些操作可能會重新在新的進程上建立緩存。這種策略在緩存命中率比較高的情況下,性能是最好的,因為一般無需查詢租約情況,就可以直接操作;但如果緩存命中率低,那么就會出現緩存反復在不同進程間“移動”,會嚴重降低系統的處理性能。
租約轉發。同樣,我們把存放某個KEY的緩存的進程,稱為持有這個KEY數據的“租約”,同時也要登記到集群的共享數據進程中。和上面租約清理不同的地方在于,如果發現持有租約的進程不是本次操作的進程,就會把整個數據的讀、寫請求,都通過網絡“轉發”個持有租約的進程,然后等待他的操作結果返回。這種做法由于每次操作都需要查詢租約,所以性能會稍微低一些;但如果緩存命中率不高,這種做法能把緩存的操作分擔到多個進程上,而且也無需清理緩存,這比租約清理的策略適應性更好。
修改廣播。上面兩種策略,都需要維護一份緩存數據的租約,但是本身對于租約的操作,就是一種比較耗費性能的事情。所以有時候可以采用一些更簡單,但可能承受一些不一致性的策略:對于讀操作,每個節點的讀都建立緩存,每次讀都判斷是否超過預設的讀冷卻時間x,超過則清理緩存從持久化重建;對于寫操作,么個節點上都判斷是否超過預設的寫冷卻時間y,超過則展開清理操作。清理操作也分兩種,如果數據量小就廣播修改數據;如果數據量大就廣播清理通知回寫到持久化中。這樣雖然可能會有一定的不一致風險,但是如果數據不是那種要求太高的,而且緩存命中率又能比較有保障的話(比如根據KEY來進行一致性哈希訪問緩存進程),那么真正因為寫操作廣播不及時,導致數據不一致的情況還是會比較少的。這種策略實現起來非常簡單,無需一個中心節點進程維護數據租約,也無需復雜的判斷邏輯進行同步,只要有廣播的能力,加上對于寫操作的一些配置,就能實現高效的緩存服務。所以“修改廣播”策略是在大多數需要實時同步,但數據一致性要求不高的領域最常見的手段。著名的DNS系統的緩存就是接近這種策略:我們要修改某個域名對應的IP,并不是立刻在全球所有的DNS服務器上生效,而是需要一定時間廣播修改給其他服務區。而我們每個DSN服務器,都具備了大量的其他域名的緩存數據。
總結
在高性能的服務器架構中,常用的緩存和分布兩種策略,往往是結合到一起使用的。雖然這兩種策略,都有無數種不同的表現形式,成為各種各樣的技術流派,但是只有清楚的理解這些技術的原理,并且和實際的業務場景結合起來,才能真正的做出滿足應用要求的高性能架構。
轉載于:https://my.oschina.net/u/2987407/blog/783652
總結
以上是生活随笔為你收集整理的高性能服务器架构思路(五)——分布式缓存的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 转】R利剑NoSQL系列文章 之 Hiv
- 下一篇: DrawerLayout侧滑详解