高性能服務器架構思路(五)——分佈式緩存

 

版權聲明:本文由韓偉原創文章,轉載請註明出處: 
文章原文連接: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集羣進程。那麼在讀、寫發生的時候,若是本進程沒有對應的緩存,就先去查詢一下對應的租約,若是被其餘進程持有,則通知對方「清理」,所謂「清理」,每每是指刪除用來讀的數據,回寫用來寫的數據到數據庫等持久化設備,等清理完成後,在進行正常的讀寫操做,這些操做可能會從新在新的進程上創建緩存。這種策略在緩存命中率比較高的狀況下,性能是最好的,由於通常無需查詢租約狀況,就能夠直接操做;但若是緩存命中率低,那麼就會出現緩存反覆在不一樣進程間「移動」,會嚴重下降系統的處理性能。spa

租約轉發。一樣,咱們把存放某個KEY的緩存的進程,稱爲持有這個KEY數據的「租約」,同時也要登記到集羣的共享數據進程中。和上面租約清理不一樣的地方在於,若是發現持有租約的進程不是本次操做的進程,就會把整個數據的讀、寫請求,都經過網絡「轉發」個持有租約的進程,而後等待他的操做結果返回。這種作法因爲每次操做都須要查詢租約,因此性能會稍微低一些;但若是緩存命中率不高,這種作法能把緩存的操做分擔到多個進程上,並且也無需清理緩存,這比租約清理的策略適應性更好。對象

修改廣播。上面兩種策略,都須要維護一份緩存數據的租約,可是自己對於租約的操做,就是一種比較耗費性能的事情。因此有時候能夠採用一些更簡單,但可能承受一些不一致性的策略:對於讀操做,每一個節點的讀都創建緩存,每次讀都判斷是否超過預設的讀冷卻時間x,超過則清理緩存從持久化重建;對於寫操做,麼個節點上都判斷是否超過預設的寫冷卻時間y,超過則展開清理操做。清理操做也分兩種,若是數據量小就廣播修改數據;若是數據量大就廣播清理通知回寫到持久化中。這樣雖然可能會有必定的不一致風險,可是若是數據不是那種要求過高的,並且緩存命中率又能比較有保障的話(好比根據KEY來進行一致性哈希訪問緩存進程),那麼真正由於寫操做廣播不及時,致使數據不一致的狀況仍是會比較少的。這種策略實現起來很是簡單,無需一箇中心節點進程維護數據租約,也無需複雜的判斷邏輯進行同步,只要有廣播的能力,加上對於寫操做的一些配置,就能實現高效的緩存服務。因此「修改廣播」策略是在大多數須要實時同步,但數據一致性要求不高的領域最多見的手段。著名的DNS系統的緩存就是接近這種策略:咱們要修改某個域名對應的IP,並非馬上在全球全部的DNS服務器上生效,而是須要必定時間廣播修改給其餘服務區。而咱們每一個DSN服務器,都具有了大量的其餘域名的緩存數據。接口

總結

在高性能的服務器架構中,經常使用的緩存和分佈兩種策略,每每是結合到一塊兒使用的。雖然這兩種策略,都有無數種不一樣的表現形式,成爲各類各樣的技術流派,可是隻有清楚的理解這些技術的原理,而且和實際的業務場景結合起來,才能真正的作出知足應用要求的高性能架構。

相關文章
相關標籤/搜索