Memcached和Redis簡介

前言:react

        目前比較流行的緩存技術無疑是Memcached和Redis,兩套緩存技術有着諸多的類似之處,但又具有大量的顯著差別,做爲新生的方案,Redis被視爲首選,可是有些場景Memcached發揮的做用是不容忽視的。redis

類似點:算法

         1. Memcached和Redis都屬於In-Memory、Key-Value數據存儲方案,同屬於NoSQL家族,都選擇將所有數據存儲在內存中。數組

         2. 都是成熟的開源項目,Memcached由Brad Fitzpatrick 2003年開發而成,Redis則由Salvatore Sanfilippo於2009建立。緩存

         3. 簡單易用,只需幾分鐘就能夠完成安裝工做。服務器

不一樣之處:數據結構

         1. Redis支持服務器端的數據操做: Redis相對Memcached擁有更多的數據結構,支持豐富的數據操做。多線程

         2. 內存使用率:Memcached簡單的key-value存儲,內存利用率更高,而若是Redis採用hash結構來作Key-value存儲,因爲組合式的壓縮,內存利用率更高。併發

         3.性能對比:Redis單核,Memcached可使用多核,因此平均每個核上Redis在存儲小數據時比Memcached性能更高。而在100k以上的數據中,Memcached性能要高於Redis,雖然Redis最近也在存儲大數據的性能上進行優化,可是比起Memcached,還有些差距。app

結合以上特性下面從二者的事件模型,內存管理,數據類型、集羣管理、持久化詳細講解一下

1、事件模型

      相同之處:都是用epol來作事件循環

      不一樣之處:redis是單線程服務器(這裏的單線程是指除了主線程之外其餘線程沒有event loop),redis事件模型只有一個event loop,是最簡單的reactor的實現。redis事件模型中有一個亮點,redis裏面的fd(詳細請百度)就是服務器與客戶端鏈接socket的fd,一般根據fd找到具體的客戶端信息,一般的處理方式就是用紅黑樹將fd與客戶端信息保存起來,經過fd查找,效率是lgn,不過redis比較特殊,redis客戶端的數量上限能夠設置,即同一時刻知道redis打開的fd的上限,且進程的fd在同一時刻是不會重複的,因此redis使用一個數據,將fd做爲數組的下標,數組的元素就是客戶端的信息,這樣經過fd就能訂位客戶端信息,查找效率是O(1),省去了紅黑樹的實現。

       Memcached是多線程的,使用Master-Worker的方式,其中主線程負責接收鏈接,而後將鏈接分給各個worker線程,在各個worker線程中完成命令的接收,處理和返回結果。

2、內存管理

  1. Memcached使用預先分配,預先分配一大塊內存,而後接下來就從內存池中分配,這樣能夠減小內存的分配次數,提升效率。Memcached的採用Slab Allocation,內存的結構決定了Value值的大小最大隻能爲1MB。

       Slab Allocation的原理:將分配的內存分割成各類尺寸的塊(chunk),並把尺寸相同的塊分紅組,每一組被稱爲slab。Memcached的內存分配以Page爲單位,Page默認值爲1M,能夠在啓動時經過-I參數來指定。Slab是由多個Page組成的,Page按照指定大小切割成多個chunk。memcached在啓動時經過-f選項能夠指定 Growth Factor因子。該值控制slab之間的差別,chunk大小的差別。默認值爲1.25。其結構圖以下:

 

  優缺點:Slab Allocation能夠有效的解決內存碎片的問題,可是也會形成內存的浪費

             1.每一個slab的chunk大小是固定的,當item的佔用空間實際小於chunk大小時,會出現內存浪費

             2.每一個slab的大小是固定的(由於page是固定的),當slab不能被他所擁有的chunk整除時,會出現內存浪費

             3.按照Growth Factor因子生成指定大小的slab,而某slab id根本未被使用時,會出現內存浪費

   2. Redis使用動態分配,因爲C語言沒有自帶的GC,因此Redis的實現中封裝了C的malloc,calloc,realloc和free函數來對本身的內存進行管理,這些實現都在zmalloc.h和zmalloc.c中。在Redis中,並非全部的數據一直存儲在內存中。當物理內存用完時,Redis能夠將一些好久沒用的Value交換到磁盤。Redis只會緩存全部的key,當Redis發現內存的使用量超過了一個閥值,將觸發Swap操做,Redis根據「swappability = age*log(size_in_memory)」計算出哪些key對應的value須要swap到磁盤。而後再將這些key對應的value持久化到磁盤中,同時在內存中清除。這種特性使得Redis能夠保持超過其機器自己內存大小的數據。固然,機器自己的內存必需要可以保持全部的key,畢竟這些數據是不會進行swap操做的。同時因爲Redis將內存中的數據swap到磁盤中的時候,提供服務的主線程和進行swap操做的子線程會共享這部份內存,因此若是更新須要swap的數據,Redis將阻塞這個操做,直到子線程完成swap操做後才能夠進行修改。當從Redis中讀取數據的時候,若是讀取的key對應的value不在內存中,那麼Redis就須要從swap文件中加載相應數據,而後再返回給請求方。 這裏就存在一個I/O線程池的問題。在默認的狀況下,Redis會出現阻塞,即完成全部的swap文件加載後纔會相應。這種策略在客戶端的數量較小,進行批量操做的時候比較合適。可是若是將Redis應用在一個大型的網站應用程序中,這顯然是沒法知足大併發的狀況的。因此Redis運行咱們設置I/O線程池的大小,對須要從swap文件中加載相應數據的讀取請求進行併發操做,減小阻塞的時間。

3、數據類型

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

四:集羣管理

     Memcached自己並不支持分佈式,只能在客戶端經過一致性hash這樣的分佈式算法來實現Memcached的分佈式存儲。 Redis更偏向服務端構建分佈式存儲,Redis Cluster是一個實現了分佈式且容許單點故障的Redis高級版本,去中心化,具備線性可伸縮的功能。節點與節點之間經過二進制協議進行通訊,節點與客戶端之間經過ascii協議進行通訊。在數據的放置策略上,Redis Cluster將整個key的數值域分紅4096個哈希槽,每一個節點上能夠存儲一個或多個哈希槽,也就是說當前Redis Cluster支持的最大節點數就是4096。Redis Cluster使用的分佈式算法也很簡單:crc16( key ) % HASH_SLOTS_NUMBER。

五:數據持久化

     Memcached不支持數據持久化。Redis支持兩種數據持久化RDB快照和AOF日誌。

     Redis Cluster引入了master-slave模式,每個master都對應兩個slave節點。

 總體上說,二者的性能都很好,沒必要爲哪一個性能更高而糾結。不過,redis提供的持久化和數據同步機制,這些都是memcached沒有的,因此若是你想要持久化,就只能用redis了。另外,memcached足以應付簡單的鍵值存儲,不過你要是想用更高級的數據結構,好比hash,list,set,zset之類的,redis提供了這些類型,用着更方便。 

相關文章
相關標籤/搜索