許多Web 應用程序都將數據保存到RDBMS中,應用服務器從中讀取數據並在瀏覽器中顯示。但隨着數據量的增大,訪問的集中,就會出現REBMS的負擔加劇,數據庫響應惡化,網站顯示延遲等重大影響。Memcached是高性能的分佈式內存緩存服務器。通常的使用目的是經過緩存數據庫查詢結果,減小數據庫的訪問次數,以提升動態Web 應用的速度、提升擴展性。
Memcached做爲高速運行的分佈式緩存服務器具備如下特色。
- 協議簡單:memcached的服務器客戶端通訊並不使用複雜的MXL等格式,而是使用簡單的基於文本的協議。
- 基於libevent的事件處理:libevent是個程序庫,他將Linux 的epoll、BSD類操做系統的kqueue等時間處理功能封裝成統一的接口。memcached使用這個libevent庫,所以能在Linux、BSD、Solaris等操做系統上發揮其高性能。
- 內置內存存儲方式:爲了提升性能,memcached中保存的數據都存儲在memcached內置的內存存儲空間中。因爲數據僅存在於內存中,所以重啓 memcached,重啓操做系統會致使所有數據消失。另外,內容容量達到指定的值以後memcached回自動刪除不適用的緩存。
- Memcached不互通訊的分佈式:memcached儘管是「分佈式」緩存服務器,但服務器端並無分佈式功能。各個memcached不會互相通訊以共享信息。他的分佈式主要是經過客戶端實現的。
Memcached的內存管理
最近的memcached默認狀況下采用了名爲Slab Allocatoion的機制分配,管理內存。在改機制出現之前,內存的分配是經過對全部記錄簡單地進行malloc和free來進行的。可是這中方式會致使內存碎片,加劇操做系統內存管理器的負擔。
Slab Allocator的基本原理是按照預先規定的大小,將分配的內存分割成特定長度的塊,已徹底解決內存碎片問題。Slab Allocation 的原理至關簡單。將分配的內存分割成各類尺寸的塊(chucnk),並把尺寸相同的塊分紅組(chucnk的集合)如圖:
並且slab allocator 還有重複使用已分配內存的目的。也就是說,分配到的內存不會釋放,而是重複利用。
Slab Allocation 的主要術語
- Page :分配給Slab 的內存空間,默認是1MB。分配給Slab 以後根據slab 的大小切分紅chunk.
- Chunk : 用於緩存記錄的內存空間。
- Slab Class:特定大小的chunk 的組。
在Slab 中緩存記錄的原理
Memcached根據收到的數據的大小,選擇最合適數據大小的Slab memcached中保存着slab內空閒chunk的列表,根據該列表選擇chunk,而後將數據緩存於其中。
Memcached在數據刪除方面有效裏利用資源
Memcached刪除數據時數據不會真正從memcached中消失。Memcached不會釋放已分配的內存。記錄超時後,客戶端就沒法再看見該記錄(invisible 透明),其存儲空間便可重複使用。
Lazy Expriationmemcached內部不會監視記錄是否過時,而是在get時查看記錄的時間戳,檢查記錄是否過時。這種技術稱爲lazy expiration.所以memcached不會再過時監視上耗費CPU時間。
對於緩存存儲容量滿的狀況下的刪除須要考慮多種機制,一方面是按隊列機制,一方面應該對應緩存對象自己的優先級,根據緩存對象的優先級進行對象的刪除。
LRU:從緩存中有效刪除數據的原理
Memcached會優先使用已超時的記錄空間,但即便如此,也會發生追加新紀錄時空間不足的狀況。此時就要使用名爲Least Recently Used (LRU)機制來分配空間。這就是刪除最少使用的記錄的機制。所以當memcached的內存空間不足時(沒法從slab class)獲取到新空間時,就從最近未使用的記錄中搜索,並將空間分配給新的記錄。
Memcached分佈式
Memcached雖然稱爲「分佈式「緩存服務器,但服務器端並無「分佈式」的功能。Memcached的分佈式徹底是有客戶端實現的。如今咱們就看一下memcached是怎麼實現分佈式緩存的。
例以下面假設memcached服務器有node1~node3三臺,應用程序要保存鍵名爲「tokyo」「kanagawa」「chiba」「saitama」「gunma」 的數據。
首先向memcached中添加「tokyo」。將「tokyo」傳給客戶端程序庫後,客戶端實現的算法就會根據「鍵」來決定保存數據的memcached服務器。服務器選定後,即命令它保存「tokyo」及其值。
一樣,「kanagawa」「chiba」「saitama」「gunma」都是先選擇服務器再保存。
接下來獲取保存的數據。獲取時也要將要獲取的鍵「tokyo」傳遞給函數庫。函數庫經過與數據保存時相同的算法,根據「鍵」選擇服務器。使用的算法相同,就能選中與保存時相同的服務器,而後發送get命令。只要數據沒有由於某些緣由被刪除,就能得到保存的值。
這樣,將不一樣的鍵保存到不一樣的服務器上,就實現了memcached的分佈式。 memcached服務器增多後,鍵就會分散,即便一臺memcached服務器發生故障沒法鏈接,也不會影響其餘的緩存,系統依然能繼續運行。
Memcached的緩存分佈策略:
http://blog.csdn.net/bintime/article/details/6259133
Consistent Hashing的簡單說明
Consistent Hashing以下所示:首先求出memcached服務器(節點)的哈希值, 並將其配置到0~232的圓(continuum)上。 而後用一樣的方法求出存儲數據的鍵的哈希值,並映射到圓上。 而後從數據映射到的位置開始順時針查找,將數據保存到找到的第一個服務器上。 若是超過232仍然找不到服務器,就會保存到第一臺memcached服務器上。
從上圖的狀態中添加一臺memcached服務器。餘數分佈式算法因爲保存鍵的服務器會發生巨大變化 而影響緩存的命中率,但Consistent Hashing中,只有在continuum上增長服務器的地點逆時針方向的 第一臺服務器上的鍵會受到影響。
所以,Consistent Hashing最大限度地抑制了鍵的從新分佈。 並且,有的Consistent Hashing的實現方法還採用了虛擬節點的思想。 使用通常的hash函數的話,服務器的映射地點的分佈很是不均勻。 所以,使用虛擬節點的思想,爲每一個物理節點(服務器) 在continuum上分配100~200個點。這樣就能抑制分佈不均勻, 最大限度地減少服務器增減時的緩存從新分佈。
緩存多副本
緩存多副本主要是用於在緩存數據存放時存儲緩存數據的多個副本,以防止緩存失效。緩存失效發生在如下幾種狀況:
- 1. 緩存超時被移除(正常失效)
- 2. 緩存因爲存儲空間限制被移除(異常失效)
- 3. 因爲緩存節點變化而致使的緩存失效(異常失效)
在緩存多副本的狀況下,須要從新考慮緩存的分佈式分佈策略。其次緩存的多個副本實際自己是可能的多個讀的節點,能夠作爲分佈式的並行讀,這是另一個能夠考慮的問題。
緩存數據的一致性問題 緩存數據儘可能只讀,所以緩存自己是不適合大量寫和更新操做的數據場景的。對於讀的狀況下,若是存在數據變化,一種是同時更新緩存和數據庫。一種是直接對緩存數據進行失效處理。