分佈式緩存Redis之與Memcached的比較

寫在前面

  本學習教程所有示例代碼見GitHub:https://github.com/selfconzrr/Redis_Learning

  由於在項目中並沒有使用Memcached,所以在這貼出Memcached的教程,以備不時之需。

  http://www.runoob.com/Memcached/Memcached-tutorial.html

  Redis的作者Salvatore Sanfilippo曾經對這兩種基於內存的數據存儲系統進行過比較,總體來看還是比較客觀的。

一、性能

  由於Redis只使用單核,而Memcached可以使用多核,所以平均每一個核上Redis在存儲小數據時比Memcached性能更高。而在100k以上的數據時,Memcached性能要高於Redis,雖然Redis最近也在存儲大數據的性能上進行優化,但是比起Memcached,還是稍有遜色。

二、內存使用效率

  使用簡單的key-value存儲的話,Memcached的內存利用率更高,而如果Redis採用hash結構來做key-value存儲,由於其組合式的壓縮,其內存利用率會高於Memcached。

三、Redis支持服務器端的數據操作

  Redis相比Memcached來說,擁有更多的數據結構並支持更豐富的數據操作,通常在Memcached裏,你需要將數據拿到客戶端來進行類似的修改再set回去,序列化再反序列化,這大大增加了網絡IO的次數和數據體積。在Redis中,這些複雜的操作通常和一般的GET/SET一樣高效。所以,如果需要緩存能夠支持更復雜的結構和操作,那麼Redis會是不錯的選擇。

  與Memcached僅支持簡單的key-value結構的數據記錄不同,Redis支持的數據類型要豐富得多。最爲常用的數據類型主要由五種:String、Hash、List、Set和Sorted Set。Redis內部使用一個redisObject對象來表示所有的key和value

四、數據備份恢復

  memcached掛掉後,數據不可恢復;redis數據丟失後可以通過aof恢復,Redis支持數據的備份,即master-slave主從模式的數據備份。

五、數據存儲

  Redis和Memcached都是將數據存放在內存中,都是內存數據庫。不過memcached還可用於緩存其他東西,例如圖片、視頻等等。memcached把數據全部存在內存之中,斷電後會掛掉,數據不能超過內存大小;redis有部份存在硬盤上,這樣能保證數據的持久性,支持數據的持久化(RDB、AOF),而Memcached不支持持久化。同時Redis並不是所有的數據都一直存儲在內存中的,當物理內存用完時,Redis可以將一些很久沒用到的value交換到磁盤,但memcached超過內存比例會抹掉前面的數據

六、內存管理機制

  對於像Redis和Memcached這種基於內存的數據庫系統來說,內存管理的效率高低是影響系統性能的關鍵因素。傳統C語言中的malloc/free函數是最常用的分配和釋放內存的方法,但是這種方法存在着很大的缺陷:首先,對於開發人員來說不匹配的malloc和free容易造成內存泄露;其次頻繁調用會造成大量內存碎片無法回收重新利用,降低內存利用率;最後作爲系統調用,其系統開銷遠遠大於一般函數調用。所以,爲了提高內存的管理效率,高效的內存管理方案都不會直接使用malloc/free調用。

  Memcached默認使用Slab Allocation機制管理內存,其主要思想是按照預先規定的大小,將分配的內存分割成特定長度的塊以存儲相應長度的key-value數據記錄,以完全解決內存碎片問題。Slab Allocation機制只爲存儲外部數據而設計,也就是說所有的key-value數據都存儲在Slab Allocation系統裏,而Memcached的其它內存請求則通過普通的malloc/free來申請,因爲這些請求的數量和頻率決定了它們不會對整個系統的性能造成影響。

  這裏寫圖片描述

  如圖所示,它首先從操作系統申請一大塊內存,並將其分割成各種尺寸的塊Chunk,並把尺寸相同的塊分成組Slab Class。其中,Chunk就是用來存儲key-value數據的最小單位。每個Slab Class的大小,可以在Memcached啓動的時候通過制定Growth Factor來控制。假定圖中Growth Factor的取值爲1.25,如果第一組Chunk的大小爲88個字節,第二組Chunk的大小就爲112個字節,依此類推。

  當Memcached接收到客戶端發送過來的數據時首先會根據收到數據的大小選擇一個最合適的Slab Class,然後通過查詢Memcached保存着的該Slab Class內空閒Chunk的列表就可以找到一個可用於存儲數據的Chunk。當一條數據庫過期或者丟棄時,該記錄所佔用的Chunk就可以回收,重新添加到空閒列表中。

  從以上過程我們可以看出Memcached的內存管理制效率高,而且不會造成內存碎片,但是它最大的缺點就是會導致空間浪費。因爲每個Chunk都分配了特定長度的內存空間,所以變長數據無法充分利用這些空間。比如將100個字節的數據緩存到128個字節的Chunk中,剩餘的28個字節就浪費掉了。Memcached主要的cache機制是LRU(最近最少使用Least Recently Used)算法+超時失效

  這裏寫圖片描述

  Redis的內存管理主要通過源碼中zmalloc.h和zmalloc.c兩個文件來實現的。Redis爲了方便內存的管理,在分配一塊內存之後,會將這塊內存的大小存入內存塊的頭部。

  這裏寫圖片描述

  如圖所示,real_ptr是redis調用malloc後返回的指針。redis將內存塊的大小size存入頭部,size所佔據的內存大小是已知的,爲size_t類型的長度,然後返回ret_ptr。當需要釋放內存的時候,ret_ptr被傳給內存管理程序。通過ret_ptr,程序可以很容易的算出real_ptr的值,然後將real_ptr傳給free釋放內存。

  Redis通過定義一個數組來記錄所有的內存分配情況,這個數組的長度爲ZMALLOC_MAX_ALLOC_STAT。數組的每一個元素代表當前程序所分配的內存塊的個數,且內存塊的大小爲該元素的下標。在源碼中,這個數組爲zmalloc_allocations。zmalloc_allocations[16]代表已經分配的長度爲16bytes的內存塊的個數。zmalloc.c中有一個靜態變量used_memory用來記錄當前分配的內存總大小。所以,總的來看,Redis採用的是包裝的mallc/free,相較於Memcached的內存管理方法來說,要簡單很多

七、集羣、分佈式存儲

  Memcached是全內存的數據緩衝系統,Redis雖然支持數據的持久化,但是全內存畢竟纔是其高性能的本質。作爲基於內存的存儲系統來說,機器物理內存的大小就是系統能夠容納的最大數據量。如果需要處理的數據量超過了單臺機器的物理內存大小,就需要構建分佈式集羣來擴展存儲能力。

  Memcached本身並不支持分佈式,因此只能在客戶端通過像一致性哈希這樣的分佈式算法來實現Memcached的分佈式存儲,關於分佈式一致性哈希算法見總結:分佈式一致性hash算法。當客戶端向Memcached集羣發送數據之前,首先會通過內置的分佈式算法計算出該條數據的目標節點,然後數據會直接發送到該節點上存儲。但客戶端查詢數據時,同樣要計算出查詢數據所在的節點,然後直接向該節點發送查詢請求以獲取數據。

  相較於Memcached只能採用客戶端實現分佈式存儲,Redis更偏向於在服務器端構建分佈式存儲,但沒有采用一致性哈希,關於Redis集羣分析見總結:分佈式緩存Redis之cluster集羣。最新版本的Redis已經支持了分佈式存儲功能。Redis Cluster是一個實現了分佈式且允許單點故障的Redis高級版本,它沒有中心節點,具有線性可伸縮的功能。爲了保證單點故障下的數據可用性,Redis Cluster引入了Master節點和Slave節點。在Redis Cluster中,每個Master節點都會有對應的兩個用於冗餘的Slave節點。這樣在整個集羣中,任意兩個節點的宕機都不會導致數據的不可用。當Master節點退出後,集羣會自動選擇一個Slave節點成爲新的Master節點。

八、Memcache支持多核多線程,Redis單線程操作

如果您覺得這篇文章對您有所啓發、有所幫助,可以給我打賞一元錢,去買個茶葉蛋吃,謝謝~~~~

微信:

這裏寫圖片描述

支付寶:

這裏寫圖片描述

—–樂於分享,共同進步,歡迎補充
—–Any comments greatly appreciated
—–誠心歡迎各位交流討論!QQ:1138517609

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章