Redis 是徹底開源免費的,遵照BSD協議,是一個高性能的key-value數據庫。可是它自己是支持內存數據的持久化的,並且提供兩種主要的持久化策略:RDB快照和AOF日誌。redis
memcache是一個分佈式的高速緩存系統,其本質上就是一個內存key-value數據庫,可是不支持數據的持久化,服務器關閉以後數據所有丟失。算法
做爲內存數據緩衝系統,Memcached和Redis均具備很高的性能,可是二者在關鍵實現技術上具備很大差別,這種差別決定了二者具備不一樣的特色和不一樣的適用條件。下面咱們會對二者的關鍵技術進行一些對比,以此來揭示二者的差別。數據庫
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個字節,依此類推。緩存
當Memcached接收到客戶端發送過來的數據時首先會根據收到數據的大小選擇一個最合適的Slab Class,而後經過查詢Memcached保存着的該Slab Class內空閒Chunk的列表就能夠找到一個可用於存儲數據的Chunk。當一條數據庫過時或者丟棄時,該記錄所佔用的Chunk就能夠回收,從新添加到空閒列表中。從以上過程咱們能夠看出Memcached的內存管理制效率高,並且不會形成內存碎片,可是它最大的缺點就是會致使空間浪費。由於每一個 Chunk都分配了特定長度的內存空間,因此變長數據沒法充分利用這些空間。如圖 4所示,將100個字節的數據緩存到128個字節的Chunk中,剩餘的28個字節就浪費掉了。服務器
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釋放內存。架構
Redis經過定義一個數組來記錄全部的內存分配狀況,這個數組的長度爲ZMALLOC_MAX_ALLOC_STAT。數組的每個元素表明當前程序所分配的內存塊的個數,且內存塊的大小爲該元素的下標。在源碼中,這個數組爲zmalloc_allocations。 zmalloc_allocations[16]表明已經分配的長度爲16bytes的內存塊的個數。zmalloc.c中有一個靜態變量 used_memory用來記錄當前分配的內存總大小。因此,總的來看,Redis採用的是包裝的mallc/free,相較於Memcached的內存管理方法來講,要簡單不少分佈式
Memcached是全內存的數據緩衝系統,Redis雖然支持數據的持久化,可是全內存畢竟纔是其高性能的本質。做爲基於內存的存儲系統來講,機器物理內存的大小就是系統可以容納的最大數據量。若是須要處理的數據量超過了單臺機器的物理內存大小,就須要構建分佈式集羣來擴展存儲能力。性能
Memcached自己並不支持分佈式,所以只能在客戶端經過像一致性哈希這樣的分佈式算法來實現Memcached的分佈式存儲。圖6 給出了Memcached的分佈式存儲實現架構。當客戶端向Memcached集羣發送數據以前,首先會經過內置的分佈式算法計算出該條數據的目標節點,而後數據會直接發送到該節點上存儲。但客戶端查詢數據時,一樣要計算出查詢數據所在的節點,而後直接向該節點發送查詢請求以獲取數據。大數據
相較於Memcached只能採用客戶端實現分佈式存儲,Redis更偏向於在服務器端構建分佈式存儲。儘管Redis當前已經發布的穩定版本尚未添加分佈式存儲功能,但Redis開發版中已經具有了Redis Cluster的基本功能。預計在2.6版本以後,Redis就會發布徹底支持分佈式的穩定版本,時間不晚於2012年末。下面咱們會根據開發版中的實現,簡單介紹一下Redis Cluster的核心思想。
Redis Cluster是一個實現了分佈式且容許單點故障的Redis高級版本,它沒有中心節點,具備線性可伸縮的功能。圖7給出Redis Cluster的分佈式存儲架構,其中節點與節點之間經過二進制協議進行通訊,節點與客戶端之間經過ascii協議進行通訊。在數據的放置策略上,Redis Cluster將整個key的數值域分紅4096個哈希槽,每一個節點上能夠存儲一個或多個哈希槽,也就是說當前Redis Cluster支持的最大節點數就是4096。Redis Cluster使用的分佈式算法也很簡單:crc16( key ) % HASH_SLOTS_NUMBER。
爲了保證單點故障下的數據可用性,Redis Cluster引入了Master節點和Slave節點。如圖4所示,在Redis Cluster中,每一個Master節點都會有對應的兩個用於冗餘的Slave節點。這樣在整個集羣中,任意兩個節點的宕機都不會致使數據的不可用。當Master節點退出後,集羣會自動選擇一個Slave節點成爲新的Master節點。
圖8 Redis Cluster中的Master節點和Slave節點