Redis - Memcached 比較

MemcachedRedis作爲兩種Inmemorykey-value數據庫,在設計和思想方面有着很多共通的地方,作爲分佈式緩存服務器使用等也很相似,在這裏把兩者放在一起做一下對比的介紹

  

基本架構和思想

首先簡單介紹一下兩者的架構和設計思路

一、Memcached

Memcached是以LiveJurnal旗下Danga Interactive公司的Bard Fitzpatric爲首開發的高性能分佈式內存緩存服務器。其本質上就是一個內存key-value數據庫,但是不支持數據的持久化,服務器關閉之後數據全部丟失。Memcached使用C語言開發,在大多數像Linux、BSD和Solaris等POSIX系統上,只要安裝了libevent即可使 用。


Memcached採用客戶端-服務器的架構,客戶端和服務器端的通訊使用自定義的協議標準,只要滿足協議格式要求,客戶端Library可以用任何語言實現。

 

從用戶的角度來說,服務器維護了一個鍵-值關係的數據表,服務器之間相互獨立,互相之間不共享數據也不做任何通訊操作。客戶端需要知道所有的服務器,並自行負責管理數據在各個服務器間的分配。

 

在服務器端,內部的數據存儲,使用基於Slab的內存管理方式,有利於減少內存碎片和頻繁分配銷燬內存所帶來的開銷。各個Slab按需動態分配一個page的內存(和4K page的概念不同,這裏默認page1M),page內部按照不同slab class的尺寸再劃分爲內存chunk供服務器存儲KV鍵值對使用

Memcached的基本應用模型如下圖所示


二、Redis

Redis是一個開源的key-value存儲系統。與Memcached類似,Redis將大部分數據存儲在內存中,支持的數據類型包括:字符串、哈希 表、鏈表、集合、有序集合以及基於這些數據類型的相關操作。Redis使用C語言開發,在大多數像Linux、BSD和Solaris等POSIX系統上無需任何外部依賴就可以使用。當前Redis的應用已經非常廣泛,國內像新浪、淘寶,國外像 Flickr、Github等均在使用Redis的緩存服務。


Redis的基本應用模式和上圖memcached的基本相似,不難發現網上到處都是關於redis是否可以完全替代memcached使用的問題

 

Redis內部的數據結構最終也會落實到key-Value對應的形式,不過從暴露給用戶的數據結構來看,要比memcached豐富,除了標準的通常意義的鍵值對,Redis還支持ListSet HashesSorted Set等數據結構

 

三、比較


1.基本命令

Memcached的命令或者說通訊協議非常簡單,Server所支持的命令基本就是對特定key的添加,刪除,替換,原子更新,讀取等,具體包括 Set, Get, Add, Replace, Append, Inc/Dec 等等

 

Memcached的通訊協議包括文本格式和二進制格式,用於滿足簡單網絡客戶端工具(如telnet)和對性能要求更高的客戶端的不同需求

 

Redis的命令在KVString類型)上提供與Memcached類似的基本操作,在其它數據結構上也支持基本類似的操作(當然還有這些數據結構所特有的操作,如SetunionListpop等)而支持更多的數據結構,在一定程度上也就意味着更加廣泛的應用場合

 

除了多種數據結構的支持,Redis相比Memcached還提供了許多額外的特性,比如Subscribe/publish命令,以支持發佈/訂閱模式這樣的通知機制等等,這些額外的特性同樣有助於拓展它的應用場景

 

Redis的客戶端-服務器通訊協議完全採用文本格式(在將來可能的服務器間通訊會採用二進制格式)

 

2.事務

redis通過Multi / Watch /Exec等命令可以支持事務的概念,原子性的執行一批命令。在2.6以後的版本中由於添加了對Script腳本的支持,而腳本固有的是以transaction事務的方式執行的,並且更加易於使用,所以不排除將來取消Multi等命令接口的可能性

 

Memcached的應用模式中,除了increment/decrement這樣的原子操作命令,不存在對事務的支持

 

3.數據備份,有效性,持久化等

memcached不保證存儲的數據的有效性,Slab內部基於LRU也會自動淘汰舊數據,客戶端不能假設數據在服務器端的當前狀態,這應該說是MemcachedFeature設定,用戶不必太多關心或者自己管理數據的淘汰更新工作,當然是否適合你的應用,取決於具體的需求,它也可能成爲你需要精確自行控制Cache生命週期的一個障礙

 

Memcached也不做數據的持久化工作,但是有許多基於memcached協議的項目實現了數據的持久化,例如memcacheDB使用BerkeleyDB進行數據存儲,但本質上它已經不是一個Cache Server,而只是一個兼容Memcached的協議key-valueData Store

 

Redis可以以master-slave的方式配置服務器,Slave節點對數據進行replica備份,Slave節點也可以充當Read only的節點分擔數據讀取的工作

 

Redis內建支持兩種持久化方案,snapshot快照和AOF 增量Log方式。快照顧名思義就是隔一段時間將完整的數據Dump下來存儲在文件中。AOF增量Log則是記錄對數據的修改操作(實際上記錄的就是每個對數據產生修改的命令本身),兩種方案可以並存,也各有優缺點,具體參見http://redis.io/topics/persistence

 

以上Redis的數據備份持久化方案等,如果不需要,爲了提高性能,也完全可以Disable

 

4.性能

性能方面,兩者都有一些自己考慮和實現

 

Memcached

memcached自身並不主動定期檢查和標記哪些數據需要被淘汰,只有當再次讀取相關數據時才檢查時間戳,或者當內存不夠使用需要主動淘汰數據時進一步檢查LRU數據

 

Redis

Redis爲了減少大量小數據CMD操作的網絡通訊時間開銷 RTT (Round Trip Time),支持pipelinescript技術

 

  • 所謂的pipeline就是支持在一次通訊中,發送多個命令給服務器批量執行,帶來的代價是服務器端需要更多的內存來緩存查詢結果。
  • Redis內嵌了LUA解析器,可以執行lua 腳本,腳本可以通過eval等命令直接執行,也可以使用script load等方式上傳到服務器端的script cache中重複使用

 

這兩種方式都可以有效地減少網絡通訊開銷,增加數據吞吐率

 

對於KV的操作,MemcachedRedis都支持MultipleGetSet命令(MemcachedMultiple Set命令貌似只在二進制的協議中支持),這同樣有利於性能的提升

 

實際性能方面,網上有很多測試比較,給出的結果各不相同,這無疑和各種測試的測試用例,測試環境,和測試時具體使用的客戶端Library實現有關。但是總體看下來,比較靠譜的結論是在kv類操作上,兩者的性能接近,Memcached的結構更加簡單,理論上應該會略微快一些。

 

 

5.集羣

memcached的服務器端互相完全獨立,客戶端通常通過對鍵值應用Hash算法決定數據的分區,爲了減少服務器的增減對Hash結果的影響,多數客戶端實現了一致性hash算法。

 

Redis在服務器端內建對集羣的支持。

6.MR類批處理應用

 

提供指定範圍的遍歷操作,是支持類似MapReduce這樣的批處理應用邏輯的關鍵之一,但是要在基於hash方式存儲的數據結構的基礎上提供這樣的支持並不容易(或者說要實現高效的範圍或遍歷操作並不容易)

 

Redis支持Scan操作用於遍歷數據集,這一操作基於其內部數據結構及實現的限制,可以保證在Scan開始時的所有數據都能被獲取到,但是不能保證不返回重複的數據,這需要由客戶端來檢查,或者客戶端對此無所謂。Scan操作還支持Match條件用來過濾鍵值,雖然存在一定的侷限性,例如match條件的比較是在獲取數據之後再執行的,效率是一個問題,更明顯的問題是不能保證每次scaniterate過程都能返回同樣數量的有效數據。

 

對於範圍操作,RedisOrdered Set支持在插入時指定數據的分數(Score)用於排序,而後支持在指定Score範圍內的各種操作,雖然由於不支持基於字符串的或自定義的基準的Range操作,這樣的範圍操作應用起來有很大的侷限性(或者說需要滿足特定的應用模式),但是還是比沒有好了

 

Memcached核心協議本身不支持任何範圍類的操作,也沒有對遍歷操作的支持,甚至不存在官方合法的列舉所有Key的操作,這當然很大程度上源於其設計思想和精簡的架構

 

此外RedisHashes數據結構,在一定程度上可以滿足獲取特定子集數據的應用邏輯需求。

 

綜上來說,如果要實現類似HBase支持的scan操作,不論是Redis還是memcached都無法做到,但是對於Redis來說,能否用於批處理類應用,不能一概而論,取決於具體的數據的格式邏輯和使用方式。通過適當的調整應用程序使用數據的方式,還是有可能在一定程度上實現對MR類批處理,或範圍查詢類應用邏輯的支持的。而對於鍵值分佈在一個較大的連續空間,數量不確定,同時又無法很好的映射爲數值進而使用ordered set來處理的這樣一些數據結構,應該還是很難高效的分區遍歷的。


四、總結


1. Redis中,並不是所有的數據都一直存儲在內存中的,這是和Memcached相比一個最大的區別。

2. Redis不僅僅支持簡單的k/v類型的數據,同時還提供list,set,hash等數據結構的存儲。

3. Redis支持數據的備份,即master-slave模式的數據備份。

4. Redis支持數據的持久化,可以將內存中的數據保持在磁盤中,重啓的時候可以再次加載進行使用。

Redis在很多方面具備數據庫的特徵,或者說就是一個數據庫系統,而Memcached只是簡單的K/V緩存


Redis作者對比redis和memcache

沒有必要過多的關心性能,因爲二者的性能都已經足夠高了。由於Redis只使用單核,而Memcached可以使用多核,所以在比較上,平均每一個核上 Redis在存儲小數據時Memcached性能更高。而在100k以上的數據中,Memcached性能要高於Redis,雖然Redis最近也在存儲 大數據的性能上進行優化,但是比起Memcached,還是稍有遜色。說了這麼多,結論是,無論你使用哪一個,每秒處理請求的次數都不會成爲瓶頸。(比如 瓶頸可能會在網卡)


如果要說內存使用效率,使用簡單的key-value存儲的話,Memcached的內存利用率更高,而如果Redis採用hash結構來做key-value存儲,由於其組合式的壓縮,其內存利用率會高於Memcached。當然,這和你的應用場景和數據特性有關。


如果你對數據持久化和數據同步有所要求,那麼推薦你選擇Redis,因爲這兩個特性Memcached都不具備。即使你只是希望在升級或者重啓系統後緩存數據不會丟失,選擇Redis也是明智的。


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


1、 Redis和Memcache都是將數據存放在內存中,都是內存數據庫。不過memcache還可用於緩存其他東西,例如圖片、視頻等等。
2、Redis不僅僅支持簡單的k/v類型的數據,同時還提供list,set,hash等數據結構的存儲。
3、虛擬內存--Redis當物理內存用完時,可以將一些很久沒用到的value 交換到磁盤
4、過期策略--memcache在set時就指定,例如set key1 0 0 8,即永不過期。Redis可以通過例如expire 設定,例如expire name 10
5、分佈式--設定memcache集羣,利用magent做一主多從;redis可以做一主多從。都可以一主一從
6、存儲數據安全--memcache掛掉後,數據沒了;redis可以定期保存到磁盤(持久化)
7、災難恢復--memcache掛掉後,數據不可恢復; redis數據丟失後可以通過aof恢復
8、Redis支持數據的備份,即master-slave模式的數據備份。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章