數據庫索引原理(2)------MemCached

Memcached是高性能的分佈式內存緩存服務器。它的主要目的不是基於本地緩存的,而主要用在分佈式系統中。Memcached中保存的數據都存儲在Memcached內置的內存存儲空間中。由於數據僅存在於內存中,因此重啓Memcached、重啓操作系統會導致全部數據消失。Memcached是記錄級的緩存,之前調研報告裏提到過與MySQL、Server等頁級緩存會緩存無效數據的,記錄級的緩存則使內存利用率更高。



 

一、Memcached的內存管理方式

memcached默認情況下采用了Slab Allocator的機制分配、管理內存。在該機制出現以前,內存的分配是通過對所有記錄簡單地進行malloc和free來進行的。但是,這種方式會導致內存碎片,加重操作系統內存管理器的負擔,Slab Allocator就是爲解決該問題而誕生的。

SlabAllocator的基本原理是按照預先規定的大小,將分配的內存分割成特定長度的塊,以完全解決內存碎片問題。下面我會介紹內存分配過程。


Memcached將內存分成多個slab,每個slab是一次申請內存的最小單位(大小爲1M不過好像可以設置),slab內部又分爲若干個chunk。chunk的大小分爲很多種,以80字節爲初始大小(稱爲id-0的slab),第二類大小爲第一類的f倍(f爲參數可調,稱這類爲id-1的slab),隨id遞增每一類比上一類的chunk大小大f倍。所以一個chunk最大隻可能爲1M。每個chunk裏包含了一個item結構體(key和value),用來存放緩存數據。chunk大小相同的已分配空間的slab組成一個鏈表,所有的slab鏈表都保存在一個slabclass的數組上(相當於二維鏈表),每一種slab在初始化時默認都會創建一個。

 

 

二、Memcached緩存記錄的原理

memcached接收到一條記錄時,首先會知道item的大小,然後就會在slabclass數組上去找能包含這個item的最小的chunk的slab鏈表(由於memcached的各鏈表之間chunk大小的倍數關係,可以快速定位到鏈表的起始位置),找到空閒的chunk緩存這條記錄。當一個slab的chunk都用完,則新申請新的slab用來存item,申請的slab的大小是倍數變化的(和std::vector一樣),鏈表大小由1變2,由2變4、8、16……如果空間已滿,不能申請更多slab,則按照LRU原則,將空間分配給新的記錄。

 

 

三、Memcached的內存浪費

memcached的內存主要表現有以下三處:

1、一個slab分配1M空間,而slab中所有chunks大小加起來可能到不了1M;

2、每類slab在初始化時默認都會創建一個,但是如果這類slab從未被使用過,則這1M就浪費了;

3、一個item的大小總是不大於chunk大小的,當小於時則發生內存冗餘。

第一類可以通過參數調優儘量減少這種內存冗餘,第二類應該也可以減少,第三類看起來就不太少避免。

 

四、Memcached的分佈式算法


Memcached的服務器端主要是用來記錄緩存和讀取,而分佈式算法即選擇哪臺服務器來尋找數據/寫入內存則由客戶端程序庫實現。方法是用Consistent Hash。

ConsistentHashing如下所示:首先求出memcached服務器(節點)的哈希值(memcached用CRC計算哈希值),並將其配置到0-232的圓上。然後用同樣的方法求出存儲數據的鍵的哈希值,並映射到圓上。然後從數據映射到的位置開始順時針查找,將數據保存到找到的第一個服務器上。


從上圖的狀態中添加一臺memcached服務器。傳統的取模算法會使大量的鍵不能哈希到之前緩存的服務器上,但Consistent Hashing中,只有在增加服務器的地點逆時針方向的第一臺服務器上的鍵會受到影響(如下圖)。


因此,Consistent Hashing最大限度地抑制了鍵的重新分佈。有的ConsistentHashing的實現方法還採用了虛擬節點的思想。使用一般的hash函數的話,服務器的映射地點的分佈非常不均勻。因此,使用虛擬節點的思想,爲每個物理節點(服務器)在continuum上分配100~200個點。這樣就能抑制分佈不均勻,最大限度地減小服務器增減時的緩存重新分佈。

 

(轉載本文請註明出處: http://blog.csdn.net/jiang1st2010/article/details/8121361)

 

發佈了40 篇原創文章 · 獲贊 43 · 訪問量 85萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章