天天看點

[讀書筆記]大型分布式網站架構設計與實踐.分布式緩存

前言:本書是對分布式系統架構涉及到的相關技術的一大學普書籍。由于很難作為開發參考,隻能但求了解。是以通篇淺讀,對分布式系統進行大緻的了解。因為寫的非常好,感覺非常有意思,自己也做不出總結。所謂的讀書筆記也就演變成了摘抄。

簡介

一個大型、穩健、成熟的分布式系統的背後,往往會設計衆多的支撐系統,我們将這些支撐系統成為分布式系統的基礎設施。除了前面所介紹的分布式協作及配置管理系統ZooKeeper,我們進行系統架構設計所依賴的基礎設施,還包括分布式緩存系統、持久化存儲、分布式消息系統、搜尋引擎、以及CDN系統、負載均衡系統、運維自動化系統等,還有實時計算系統、離線計算系統、分布式檔案系統、日志收集系統、監控系統、資料倉庫等。

分布式緩存

在高并發環境下,大量的讀、寫請求湧向資料庫,磁盤的處理速度與記憶體顯然不在一個量級,從減輕資料庫的壓力和提供系統響應速度兩個角度來考慮,一般都會在資料庫之前加一層緩存。由于單台機器的記憶體資源和承載能力有限,并且如果大量使用本地緩存,也會使相同的資料被不同的節點存儲多份,對記憶體資源造成較大的浪費,是以才催生出了分布式緩存。

接下來将介紹分布式緩存的典型代表memcache,以及分布式緩存的應用場景。最為典型的場景莫過于分布式session。

memcache

memcache是一款開源的高性能的分布式内容對象緩存系統,被許多大型網站所采用,用于在應用中減少對資料庫的通路,提高應用的通路速度,并降低資料庫的負載。為了在記憶體中提供資料的高速查找能力,memcache使用key-value形式存儲和通路資料,在記憶體中維護一張巨大的HashTable,使得對資料查詢的時間複雜度降低到O(1),保證了對資料的高性能通路。記憶體的空間總是有限的,當記憶體沒有更多的空間來存儲新的資料時,memcache就會使用LRU(Least Recently Used)算法,将最近不常通路的資料淘汰掉,以騰出空間來存放新的資料。memcache存儲支援的資料格式也是靈活多樣的,通過對象的序列化機制,可以将更高層的對象轉換成為二進制資料,存儲在緩存伺服器中,目前端應用需要時,又可以通過二進制内容反序列化,将資料還原成原有對象。

memcache用戶端與服務端通過建構在TCP協定之上的memcache協定來進行通信,協定支援兩種資料的傳遞,這兩種資料分别為文本行和非結構化資料。文本行主要用來承載用戶端的指令及服務端的響應,而非結構化資料則主要用于用戶端和服務端資料的傳遞。由于非結構化資料采用位元組流的形式在用戶端和服務端之間進行傳輸和存儲,是以使用方式非常靈活,緩存資料存儲幾乎沒有任何限制,并且服務端也不需要關心存儲的具體内容及位元組序。

memcache的分布式實作

memcache本身并不是一種分布式的緩存系統,它的分布式是由通路它的用戶端來實作的。一種比較簡單的實作方式是根據緩存的key來進行Hash,當後端有N台緩存伺服器時,通路的伺服器為hash(key)%N,這樣可以将前端的請求均衡地映射到後端的緩存伺服器。但這樣也會導緻一個問題,一旦後端某台緩存伺服器當機,或者是由于叢集壓力過大,需要新增緩存伺服器時,大部分的key将會重新分布。對于高并發系統來說,這可能會演變成一場災難,所有的請求将如洪水般瘋狂地湧向後端的資料庫伺服器,而資料庫伺服器的不可用,将會導緻整個應用的不可用,形成所謂的“雪崩效應”。

consistent Hash算法

使用consistent Hash算法能夠在一定程度上改善上述問題。該算法早在1997年就在論文Consistent hashing and random trees中被提出,它能夠在移除/添加一台緩存伺服器時,盡可能小地改變已存在的key映射關系,避免大量key的重新映射。

consistent Hash的原理是這樣的,它将Hash函數的值域空間組織成一個圓環,假設Hash函數的值域空間為0~(2的32次方-1),也就是Hash值是一個32位的無符号整型,整個空間按照順時針的方向進行組織,然後對相應的伺服器節點進行Hash,将他們映射到Hash環上,假設有4台伺服器分别為node1,node2,node3,node4,它們在環上的位置如圖所示。

[讀書筆記]大型分布式網站架構設計與實踐.分布式緩存

接下來使用相同的Hash函數,計算出對應的key的Hash值在環上對應的位置。根據consistent Hash算法,按照順時針方向,分布在node1與node2之間的key,它們的通路請求會被定位到node2,而node2與node4之間的key,通路請求會被定位到node4,以此類推。

假設有新的節點node5增加進來時,假設它被Hash到node2與node4之間,那麼受影響的隻有node2和node5之間的key,它們将被重新映射到node5,而其他key的映射關系将不會發生改變,這樣避免了大量key的重新映射。

當然上面描繪的知識一種理想的情況,各個節點在環上分布得十分均勻。正常情況下,當節點資料較少時,節點的分布可能十分不均勻,進而導緻資料通路的傾斜,大量的key被映射到同一台伺服器上。為了避免這種情況的出現,可以引入虛拟節點的機制,對每一個伺服器節點都計算多個Hash值,每一個Hash值都對應環上一個節點的位置,該節點稱為虛拟節點,而key的映射方式不變,隻是多了一步從虛拟節點再映射到真實節點的過程。這樣,如果虛拟節點的數量足夠多,即使隻有很少的實際節點,也能夠使key分布得相對均衡。

分布式session

對于大型分布式網站來說,支撐其業務的遠遠不止一台伺服器,而是一個分布式叢集,請求在不同伺服器之間跳轉。那麼如何保持伺服器之間的session同步呢?傳統網站一般通過将一部分資料存儲在cookie中,來規避分布式環境下session的操作。這樣做的弊端很多,一方面cookie的安全性一直廣為诟病,另一方面cookie存儲資料的大小是有限制的。随着移動網際網路的發展,很多情況下還得兼顧移動端的session需求,使得采用cookie來進行session同步的方式的弊端更為凸顯。分布式session正是在這種情況下應運而生的。

對于系統可靠性要求較高的使用者,可以将session持久化到DB中,這樣可以保證當機時會話不易丢失,但缺點也是顯而易見的,系統的整體吞吐将受到很大的影響。另一種解決方案便是将session統一存儲到緩存叢集上,如memcache,這樣可以保證較高的讀、寫性能,這一點對于并發量大的系統來說非常重要;并且從安全性考慮,session比較是有有效期的,使用緩存存儲,也便于利用緩存的失效機制。使用緩存的缺點是,一旦緩存重新開機,裡面儲存的會話也就丢失了,需要重建立立會話。