高效能伺服器架構思路 五 分布式快取

2021-07-24 10:50:16 字數 2414 閱讀 9396

在分布式程式架構中,如果我們需要整個體系有更高的穩定性,能夠對程序容災或者動態擴容提供支援,那麼最難解決的問題,就是每個程序中的記憶體狀態。因為程序一旦毀滅,記憶體中的狀態會消失,這就很難不影響提供的服務。所以我們需要一種方法,讓程序的記憶體狀態,不太影響整體服務,甚至最好能變成「無狀態」的服務。當然「狀態」如果不寫入磁碟,始終還是需要某些程序來承載的。在現在流行的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伺服器,都具備了大量的其他網域名稱的快取資料。

總結在高效能的伺服器架構中,常用的快取和分布兩種策略,往往是結合到一起使用的。雖然這兩種策略,都有無數種不同的表現形式,成為各種各樣的技術流派,但是只有清楚的理解這些技術的原理,並且和實際的業務場景結合起來,才能真正的做出滿足應用要求的高效能架構。

高效能伺服器架構思路 一 緩衝策略

在伺服器端程式開發領域,效能問題一直是備受關注的重點。業界有大量的框架 元件 類庫都是以效能為賣點而廣為人知。然而,伺服器端程式在效能問題上應該有何種基本思路,這個卻很少被這些專案的文件提及。本文正式希望介紹伺服器端解決效能問題的基本策略和經典實踐,並分為幾個部分來說明 快取策略的概念和例項 快取策...

高效能伺服器架構思路 一 緩衝策略

在伺服器端程式開發領域,效能問題一直是備受關注的重點。業界有大量的框架 元件 類庫都是以效能為賣點而廣為人知。然而,伺服器端程式在效能問題上應該有何種基本思路,這個卻很少被這些專案的文件提及。本文正式希望介紹伺服器端解決效能問題的基本策略和經典實踐,並分為幾個部分來說明 快取策略的概念和例項 快取策...

高效能伺服器架構思路 一 緩衝策略

在伺服器端程式開發領域,效能問題一直是備受關注的重點。業界有大量的框架 元件 類庫都是以效能為賣點而廣為人知。然而,伺服器端程式在效能問題上應該有何種基本思路,這個卻很少被這些專案的文件提及。本文正式希望介紹伺服器端解決效能問題的基本策略和經典實踐,並分為幾個部分來說明 快取策略的概念和例項 快取策...