Couchbase vs Redis,究竟哪一個更勝一籌?

Redis 和Couchbase都是基於內存的數據存儲系統。在它們各自的官方描述中,Couchbase是高性能,高伸縮性和高可用的分佈式緩存系統;Redis是一個開源的內存數據結構存儲系統。web

 

【權威比較】redis

Redis的做者Salvatore Sanfilippo曾經對這兩種基於內存的數據存儲系統進行過比較:算法

 

● Redis支持服務器端的數據操做
Redis相比Couchbase來講,擁有更多的數據結構和並支持更豐富的數據操做,一般在Couchbase裏,你須要將數據拿到客戶端來進行相似的修改再set回去(你須要先先經過get方法從服務器讀取數據文檔,並將文檔反序列化爲json對象,以後修改json對象對應屬性,再經過set方法將數據寫入服務器,序列化後進行存儲)。這大大增長了網絡IO的次數和傳輸中的數據體積。在Redis中,這些複雜的操做一般和通常的GET/SET同樣高效。數據庫


● 內存使用效率對比
使用簡單的key-value存儲的話,Couchbase的內存利用率更高,而Redis採用hash結構來作key-value存儲,因爲其組合式的壓縮,其內存利用率會高於Couchbase。因此,若是須要緩存可以支持更復雜的數據結構和更頻繁數據的部分更新操做,那麼Redis會是不錯的選擇。(下文會在關於數據存儲模型來證實這一點)json


● 性能對比
因爲Redis只使用單核,而Couchbase可使用多核,因此平均每個核上Redis在存儲小數據時比Couchbase性能更高。而在100k以上的數據中,Couchbase性能要高於Redis,雖然Redis最近也在存儲大數據的性能上進行優化,可是比起Couchbase,仍是稍有遜色。後端

 

其實不管是在大塊數據仍是大數據量的處理上,Couchbase都要優於Redis,不少平臺都是採用Couchbase來管理數千萬熱數據。因此,若是緩存大多數狀況下僅僅須要提供數據新增和查詢操做,那Couchbase基於文檔類型的存儲結構可以始終如一地爲提供亞毫秒的查詢體驗,對於預約義的數據類型你還能夠經過建立索引進一步優化性能,這種狀況下,Couchbase無疑是你更好的選擇。
(原話中比較的是Memcached,Couchbase做爲Memcached的增強版,繼承了其技術實現)數組

 

【Redis的優點】緩存

一.豐富的數據結構安全

Redis支持字符串、哈希表、列表、集合、有序集合,位圖,hyperloglogs等數據類型。而Couchbase僅僅支持json格式。若是有粉絲列表,排行榜,消息隊列等功能需求,選擇Redis能給你帶來很大的便利,由於它豐富的數據結構可以簡化開發和交互步驟。服務器

 

爲了證實Redis的優點,咱們簡單舉個實例對比,來描述下Hash的應用場景。

 

▲數據存儲於Couchbase

包含如下信息:用戶ID爲查找的key,存儲的value用戶對象包含姓名,年齡,生日等信息,若是用普通的key/value結構來存儲,在Couchbase中有如下2種存儲方式。

▪ 第一種方式將用戶ID做爲查找key,把其餘信息封裝成一個對象以序列化的方式存儲,這種方式的缺點是,增長了序列化/反序列化的開銷,而且在須要修改其中一項信息時,須要把整個對象取回,而且修改操做須要對併發進行保護,引入CAS等複雜問題。

 

▪ 第二種方法是用戶信息對象有多少成員就存成多少個key-value對,用戶ID+對應屬性的名稱做爲惟一標識來取得對應屬性的值,雖然省去了序列化開銷和併發問題,可是用戶ID爲重複存儲,若是存在大量這樣的數據,內存浪費仍是很是可觀的。

▲數據存儲於Redis中

Key仍然是用戶ID, value是一個Map,這個Map的key是成員的屬性名,value是屬性值,這樣對數據的修改和存取均可以直接經過其內部Map的Key(Redis裏稱內部Map的key爲field), 也就是經過 key(用戶ID) + field(屬性標籤) 就能夠操做對應屬性數據了,既不須要重複存儲數據,也不會帶來序列化和併發修改控制的問題。這也就是Redis做者高內存利用率的論據。


所以,若是有大量大有複雜結構的數據須要緩存,redis是更好的選擇,它不只能簡化你的存儲設計,還能幫你避免更新操做時繁瑣的序列號和反序列化。像twitter的關注列表,粉絲列表等就是選用了redis的list,Agora Games的排行榜就是選用了redis的有序集合。


二. counter--計數器

redis和couchbase都提供了counter這一特殊數據類型,不少平臺都是以counter爲基礎實現的流控和計數功能。但counter不一樣於其餘數據,它對實時性的要求很是高,所以十分考驗緩存系統的主鍵失效策略。這裏簡單提一下,大多數緩存系統都提供了積極失效和消極失效兩種策略保證失效數據清理。


▪ 積極策略採用定時定比例抽樣清理策略
▪ 消極策略則屬於請求觸發式的,這裏咱們主要對消極策略展開敘述。


Redis 2.6以後的版本採用毫秒爲單位存儲過時時間,每次數據訪問操做都須要進行過時檢驗,由此保證毫秒級別的過時精度。而couchbase的過時精度是秒級別的,也就是說若是你選擇了couchbase且沒有在counter上作特殊處理,你的流控將變得極不許確,更危險的是這個問題是由底層機制引起的,你幾乎不可能經過業務代碼來修復bug。好比你限制一個客戶每秒只能訪問500次,但實際狀況是客戶平均下來每秒只能訪問不到300次,這就是計數器延遲失效引起的問題。


所以,若是選擇Couchbase,要實現準確的流控和計數可能要手動爲每個計數器的key添加時間戳,並經過取餘操做限制counter的峯值數量,固然若是你難以保證全部服務器時鐘同步,你能夠指定服務器的時間,這也算是Couchbase方案的靈活性吧。


總而言之,若是你有高精度的流控和計數類需求,又不想對原生的counter二次封裝,請選擇redis。


三.事務

相比Couchbase,Redis提供了事務的功能,能夠保證一串命令的原子性,中間不會被任何操做打斷,主要命令包括主要命令包括 MULTI、EXEC、WATCH 命令。若是對事務有所要求,redis是個更好的選擇。


四. 開源社區的繁榮

Redis在國內大熱,愛好者們不只翻譯了官網,更爲其量身定作了不少優化方案,各類中文技術文檔也是包羅萬象。相比而言,Couchbase的商業版和社區版差異巨大,更趨近於閉源,網上中文資料少得可憐,全部技術文檔都須要翻閱英文官網。


所以,若是你的開發團隊缺乏很好的英文閱讀能力,redis是更好的選擇。


五.豐富的使用場景

Redis能夠適配豐富的場景,有如下五種爲最爲常見:


▲會話緩存(Session Cache)

這是最經常使用的一種使用Redis的情景。


▲全頁緩存(FPC)

除基本的會話token以外,Redis還提供很簡便的FPC平臺。以Magento爲例,Magento提供一個插件來使用Redis做爲全頁緩存後端。


▲隊列

Reids在內存存儲引擎領域的一大優勢是提供 list 和 set 操做,這使得Redis能做爲一個很好的消息隊列平臺來使用。Redis做爲隊列使用的操做,就相似於本地程序語言(如Python)對 list 的 push/pop 操做。
例如,Celery有一個後臺就是使用Redis做爲broker。


▲排行榜/計數器

Redis在內存中對數字進行遞增或遞減的操做實現的很是好。集合(Set)和有序集合(Sorted Set)也使得咱們在執行這些操做的時候變的很是簡單,Redis只是正好提供了這兩種數據結構。

因此,咱們要從排序集合中獲取到排名最靠前的10個用戶–咱們稱之爲「user_scores」,咱們只須要像下面同樣執行便可。固然,這是假定是根據用戶的分數作遞增的排序。若是想返回用戶及用戶的分數,你須要這樣執行:
ZRANGE user_scores 0 10 WITHSCORES
Agora Games就是一個很好的例子,用Ruby實現的,它的排行榜就是使用Redis來存儲數據的。


▲發佈/訂閱

發佈/訂閱的使用場景確實很是多。不只在社交網絡鏈接中使用,還可做爲基於發佈/訂閱的腳本觸發器,甚至用Redis的發佈/訂閱功能來創建聊天系統。

 

【Couchbase的優點】

一.web界面

Couchbase提供了良好的管理界面,集配置,管理,監控和告警於一身。Couchbase的web界面提供了版本提醒,ssl證書配置,用戶管理,郵件告警等一系列豐富的功能,大大簡化了運維的工做;也web界面能夠直觀的觀測OPS,磁盤寫入隊列,內存數據量,Compaction和Ejection實時情況,爲開發和測試提供了直觀的數據參考。對性能測試相當重要。而redis就僅有第三方提供的一些簡單客戶端產品,用於觀測數據存儲狀況,配置優化相關的工做也須要在配置文件中操做。

 

若是考慮到後期性能測試以及運維的可操做性,couchbase是更好的選擇。


二. 三高

這裏的三高指的是高性能,高可用性和高伸縮性。


Redis從一開始就是單點解決方案,直到Redis3.0後纔出來官方的集羣方案,並且仍存在一些架構上的問題,其高可用性目前尚未在線上被證實,第三方的集羣方案像豌豆莢的Codi又缺乏官方的後續支持。


相比而言,Couchbase從一開始就內建集羣系統,即便是節點重啓,數據未徹底載入內存,也能照常提供服務,這得益於每份數據的metedata,其中包含近期的操做信息,Couchbase藉此來區分熱數據,只要熱數據加載到最低水位便可當即提供服務。


若是出現節點失效,集羣可在指定的時間裏自動發現並啓動failover,這裏不一樣Redis的哨兵系統,Couchbase採用激活失效節點備份將請求分攤給倖存節點的方案,恢復時間更快;若是節點新增,Couchbase會將內存數據複製,一份用於提供服務,一份用於重分配並時刻保證數據一致性,即集羣擴容不會致使任何業務中斷。此外,couchbase的異步持久化和備份同步(經過維護一個持久化隊列)也要優於redis的RDB快照和AOF日誌方案。所以,從三高的角度來看,高可用性和高伸縮性上Couchbase顯然是更加可靠的。


Couchbase的集羣方案相比Redis,對用戶屏蔽了更多細節,集羣更具彈性,且通過多年的生產線上驗證。所以,若是高可用和彈性是重要考慮因素,那Couchbase無疑是更穩妥的方案。

兩款產品直觀的優點如上,你們能夠根據本文結合實際業務場景進行選擇。有興趣的同窗推薦閱讀《Seven Databases in Seven Weeks》。

 

【Redis vs Couchbase內存管理分析】

對於像Redis和Couchbase基於內存的數據庫系統來講,內存管理的效率高低是影響系統性能的關鍵因素。

 

Couchbase內存管理分析

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

 

Slab Allocation的原理至關簡單。 如圖所示,它首先從操做系統申請一大塊內存,並將其分割成各類尺寸的塊Chunk,並把尺寸相同的塊分紅組Slab Class。其中,Chunk就是用來存儲key-value數據的最小單位。每一個Slab Class的大小,能夠在Couchbase啓動的時候經過制定Growth Factor來控制。假定圖中Growth Factor的取值爲1.25,若是第一組Chunk的大小爲88個字節,第二組Chunk的大小就爲110個字節,依此類推。 

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


從以上過程咱們能夠看出Couchbase的內存管理制效率高,並且不會形成內存碎片,可是它最大的缺點就是會致使空間浪費。由於每一個Chunk都分配了特定長度的內存空間,因此變長數據沒法充分利用這些空間。如圖 所示,將100個字節的數據緩存到128個字節的Chunk中,剩餘的28個字節就浪費掉了(這就是內部碎片,但相比外部碎片是可控的,也是可再利用的)。

▲Redis內存管理分析

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,相較於Couchbase的內存管理方法來講,要簡單不少。


總的來講,Couchbase的內存管理機制以每次分配冗餘空間爲代價,避免了內存碎片。若是程序須要頻繁短時效的百字節以上的內存空間,好比動態令牌,Couchbase顯然是更好的選擇;若是僅僅使用長效的計數器或幾個字節的標識字段,那麼使用Couchbase反而形成內存浪費,Redis倒是更好的選擇。

 

【集羣管理】

一. Couchbase集羣管理

Couchbase自己並不支持分佈式,所以只能在客戶端經過像一致性哈希這樣的分佈式算法來實現Couchbase的分佈式存儲,Couchbase會經過在集羣內部和客戶端直接共享vbucket和節點映射關係,客戶端每次操做前須要對數據的key進行計算,以肯定數據落入的vbucket編號,再根據映射表肯定數據所在節點,而後直接與指定節點通訊,不須要Redis的節點重定位方案,對於集羣變動對外也只須要更新vbucket和節點映射關係便可。下圖是Couchbase的分佈式存儲實現架構。

 

如今咱們模擬一下Couchbase的失效備援方案,假設當前客戶端的vbucket和節點映射關係以下:

 

那麼當D節點失效後,集羣只須要激活ABC上D節點的數據副本,而後更新vbucket和節點映射關係以下:

此後全部的數據請求就被分攤到了ABC之上,即便客戶端的配置文件裏還存在節點D的地址,也不會再產生交互了。

二. Redis集羣管理
相較於Couchbase只能採用客戶端實現分佈式存儲,Redis更偏向於在服務器端構建分佈式存儲。最新版本的Redis已經支持了分佈式存儲功能。Redis Cluster是一個實現了分佈式且容許單點故障的Redis高級版本,它沒有中心節點,具備線性可伸縮的功能。

下圖是Redis Cluster的分佈式存儲架構:

其中節點與節點之間經過二進制協議進行通訊,節點與客戶端之間經過ascii協議進行通訊。在數據的放置策略上,Redis Cluster將整個key的數值域分紅4096個哈希槽,每一個節點上能夠存儲一個或多個哈希槽,也就是說當前Redis Cluster支持的最大節點數就是4096。Redis Cluster使用的分佈式算法也很簡單:crc16( key ) % HASH_SLOTS_NUMBER。

 

爲了保證單點故障下的數據可用性,Redis Cluster引入了Master節點和Slave節點。在Redis Cluster中,每一個Master節點都會有對應的兩個用於冗餘的Slave節點。這樣在整個集羣中,任意兩個節點的宕機都不會致使數據的不可用。當Master節點退出後,集羣會自動選擇一個Slave節點成爲新的Master節點。

 

總而言之,Couchbase把數據分佈計算分攤給客戶端執行,節省了緩存服務器的CPU,而且客戶端直接和數據所在節點通訊節省了帶寬並縮短了響應時間。且相比Redis至少須要6個實例才能組成集羣的限制,Couchbase的集羣方案更加靈活(但Redis能夠一機多個實例,Couchbase單機只能部署一個)。

 

所以,若是機器資源充足,Couchbase能夠提供更好的服務體驗(因爲客戶端分攤計算成本,這裏的機器不須要過多CPU),若是隻有機器資源緊張,redis是部署上的輕量級方案,但前面提到的,當訪問量爆發時,可能會考驗緩存服務器的CPU。

 

【該怎麼選擇】

在我看來,Conchbase和Redis本就是定位不一樣的兩款產品。Redis的亮點在於業務契合度高,Couchbase的亮點在於高可用。若是不是二選一的場景,它們是能夠相輔相成的,Redis的定位是一個帶有豐富數據結構的內存數據庫,充分利用其數據結構能夠簡化許多業務場景下的開發,如利用隊列實現消息隊列,利用有序集合實現排行榜;而Couchbase的定位是一個專業的分佈式緩存系統,將一些業務關鍵信息,如鑑權信息和會話信息存儲其中,能最大限度保證業務的安全性和高可用性。

 

Redis&Conchbase的緩存系統選型:

相關文章
相關標籤/搜索