3. Memcached和Redis關鍵技術對比html
做爲內存數據緩衝系統,Memcached和Redis均具備很高的性能,可是二者在關鍵實現技術上具備很大差別,這種差別決定了二者具備不一樣的特色和不一樣的適用條件。下面咱們會對二者的關鍵技術進行一些對比,以此來揭示二者的差別。redis
3.1 Memcached和Redis的內存管理機制對比數據庫
對於像Redis和Memcached這種基於內存的數據庫系統來講,內存管理的效率高低是影響系統性能的關鍵因素。傳統C語言中的malloc/free函數是最經常使用的分配和釋放內存的方法,可是這種方法存在着很大的缺陷:首先,對於開發人員來講不匹配的malloc和free容易形成內存泄露;其次,頻繁調用會形成大量內存碎片沒法回收從新利用,下降內存利用率;最後,做爲系統調用,其系統開銷遠遠大於通常函數調用。因此,爲了提升內存的管理效率,高效的內存管理方案都不會直接使用malloc/free調用。Redis和Memcached均使用了自身設計的內存管理機制,可是實現方法存在很大的差別,下面將會對二者的內存管理機制分別進行介紹。數組
3.1.1 Memcached的內存管理機制緩存
Memcached默認使用Slab Allocation機制管理內存,其主要思想是按照預先規定的大小,將分配的內存分割成特定長度的塊以存儲相應長度的key-value數據記錄,以徹底解決內存碎片問題。Slab Allocation機制只爲存儲外部數據而設計,也就是說全部的key-value數據都存儲在Slab Allocation系統裏,而Memcached的其它內存請求則經過普通的malloc/free來申請,由於這些請求的數量和頻率決定了它們不會對整個系統的性能形成影響架構
Slab Allocation的原理至關簡單。 如圖3所示,它首先從操做系統申請一大塊內存,並將其分割成各類尺寸的塊Chunk,並把尺寸相同的塊分紅組Slab Class。其中,Chunk就是用來存儲key-value數據的最小單位。每一個Slab Class的大小,能夠在Memcached啓動的時候經過制定Growth Factor來控制。假定Figure 1中Growth Factor的取值爲1.25,因此若是第一組Chunk的大小爲88個字節,第二組Chunk的大小就爲112個字節,依此類推。ide
圖3 Memcached內存管理架構函數
當Memcached接收到客戶端發送過來的數據時首先會根據收到數據的大小選擇一個最合適的Slab Class,而後經過查詢Memcached保存着的該Slab Class內空閒Chunk的列表就能夠找到一個可用於存儲數據的Chunk。當一條數據庫過時或者丟棄時,該記錄所佔用的Chunk就能夠回收,從新添加到空閒列表中。從以上過程咱們能夠看出Memcached的內存管理制效率高,並且不會形成內存碎片,可是它最大的缺點就是會致使空間浪費。由於每一個Chunk都分配了特定長度的內存空間,因此變長數據沒法充分利用這些空間。如圖 4所示,將100個字節的數據緩存到128個字節的Chunk中,剩餘的28個字節就浪費掉了。性能
3.1.2 Redis的內存管理機制
Redis的內存管理主要經過源碼中zmalloc.h和zmalloc.c兩個文件來實現的。Redis爲了方便內存的管理,在分配一塊內存以後,會將這塊內存的大小存入內存塊的頭部。如圖 5所示,real_ptr是redis調用malloc後返回的指針。redis將內存塊的大小size存入頭部,size所佔據的內存大小是已知的,爲size_t類型的長度,而後返回ret_ptr。當須要釋放內存的時候,ret_ptr被傳給內存管理程序。經過ret_ptr,程序能夠很容易的算出real_ptr的值,而後將real_ptr傳給free釋放內存。
圖5 Redis塊分配
Redis經過定義一個數組來記錄全部的內存分配狀況,這個數組的長度爲ZMALLOC_MAX_ALLOC_STAT。數組的每個元素表明當前程序所分配的內存塊的個數,且內存塊的大小爲該元素的下標。在源碼中,這個數組爲zmalloc_allocations。zmalloc_allocations[16]表明已經分配的長度爲16bytes的內存塊的個數。zmalloc.c中有一個靜態變量used_memory用來記錄當前分配的內存總大小。因此,總的來看,Redis採用的是包裝的mallc/free,相較於Memcached的內存管理方法來講,要簡單不少。