天天看點

高性能伺服器架構(三):分布式緩存總結

  在分布式程式架構中,如果我們需要整個體系有更高的穩定性,能夠對程序容災或者動态擴容提供支援,那麼最難解決的問題,就是每個程序中的記憶體狀态。因為程序一旦毀滅,記憶體中的狀态會消失,這就很難不影響提供的服務。是以我們需要一種方法,讓程序的記憶體狀态,不太影響整體服務,甚至最好能變成“無狀态”的服務。當然“狀态”如果不寫入磁盤,始終還是需要某些程序來承載的。在現在流行的WEB開發模式中,很多人會使用PHP+Memcached+MySQL這種模型,在這裡,PHP就是無狀态的,因為狀态都是放在Memcached裡面。這種做法對于PHP來說,是可以随時動态的毀滅或者建立,但是Memcached程序就要保證穩定才行;而且Memcached作為一個額外的程序,和它通信本身也會消耗更多的延遲時間。是以我們需要一種更靈活和通用的程序狀态儲存方案,我們把這種任務叫做“分布式緩存”的政策。我們希望程序在讀取資料的時候,能有最高的性能,最好能和在堆記憶體中讀寫類似,又希望這些緩存資料,能被放在多個程序内,以分布式的形态提供高吞吐的服務,其中最關鍵的問題,就是緩存資料的同步。

高性能伺服器架構(三):分布式緩存總結

  為了解決這個問題,我們需要先一步步來分解這個問題:

  首先,我們的緩存應該是某種特定形式的對象,而不應該是任意類型的變量。因為我們需要對這些緩存進行标準化的管理,盡管C++語言提供了運算重載,我們可以對“=”号的寫變量操作進行重新定義,但是現在基本已經沒有人推薦去做這樣的事。而我們手頭就有最常見的一種模型,适合緩存這種概念的使用,它就是——哈希表。所有的哈希表(或者是Map接口),都是把資料的存放,分為key和value兩個部分,我們可以把想要緩存的資料,作為value存放到“表”當中,同時我們也可以用key把對應的資料取出來,而“表”對象就代表了緩存。

  其次,我們需要讓這個“表”能在多個程序中都存在。如果每個程序中的資料都毫無關聯,那問題其實就非常簡單,但是如果我們可能從A程序把資料寫入緩存,然後在B程序把資料讀取出來,那麼就比較複雜了。我們的“表”要有能把資料在A、B兩個程序間同步的能力。是以我們一般會用三種政策:租約清理、租約轉發、修改廣播

  租約清理,一般是指,我們把存放某個key的緩存的程序,稱為持有這個key的資料的“租約”,這個租約要登記到一個所有程序都能通路到的地方,比如是ZooKeeper叢集程序。那麼在讀、寫發生的時候,如果本程序沒有對應的緩存,就先去查詢一下對應的租約,如果被其他程序持有,則通知對方“清理”,所謂“清理”,往往是指删除用來讀的資料,回寫用來寫的資料到資料庫等持久化裝置,等清理完成後,在進行正常的讀寫操作,這些操作可能會重新在新的程序上建立緩存。這種政策在緩存命中率比較高的情況下,性能是最好的,因為一般無需查詢租約情況,就可以直接操作;但如果緩存命中率低,那麼就會出現緩存反複在不同程序間“移動”,會嚴重降低系統的處理性能。

高性能伺服器架構(三):分布式緩存總結

   租約轉發。同樣,我們把存放某個KEY的緩存的程序,稱為持有這個KEY資料的“租約”,同時也要登記到叢集的共享資料程序中。和上面租約清理不同的地方在于,如果發現持有租約的程序不是本次操作的程序,就會把整個資料的讀、寫請求,都通過網絡“轉發”個持有租約的程序,然後等待他的操作結果傳回。這種做法由于每次操作都需要查詢租約,是以性能會稍微低一些;但如果緩存命中率不高,這種做法能把緩存的操作分擔到多個程序上,而且也無需清理緩存,這比租約清理的政策适應性更好

高性能伺服器架構(三):分布式緩存總結

  修改廣播。上面兩種政策,都需要維護一份緩存資料的租約,但是本身對于租約的操作,就是一種比較耗費性能的事情。是以有時候可以采用一些更簡單,但可能承受一些不一緻性的政策:對于讀操作,每個節點的讀都建立緩存,每次讀都判斷是否超過預設的讀冷卻時間x,超過則清理緩存從持久化重建;對于寫操作,麼個節點上都判斷是否超過預設的寫冷卻時間y,超過則展開清理操作。清理操作也分兩種,如果資料量小就廣播修改資料;如果資料量大就廣播清理通知回寫到持久化中。這樣雖然可能會有一定的不一緻風險,但是如果資料不是那種要求太高的,而且緩存命中率又能比較有保障的話(比如根據KEY來進行一緻性哈希通路緩存程序),那麼真正因為寫操作廣播不及時,導緻資料不一緻的情況還是會比較少的。這種政策實作起來非常簡單,無需一個中心節點程序維護資料租約,也無需複雜的判斷邏輯進行同步,隻要有廣播的能力,加上對于寫操作的一些配置,就能實作高效的緩存服務。是以“修改廣播”政策是在大多數需要實時同步,但資料一緻性要求不高的領域最常見的手段。著名的DNS系統的緩存就是接近這種政策:我們要修改某個域名對應的IP,并不是立刻在全球所有的DNS伺服器上生效,而是需要一定時間廣播修改給其他服務區。而我們每個DSN伺服器,都具備了大量的其他域名的緩存資料。

高性能伺服器架構(三):分布式緩存總結

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