前言
咱們都知道,Redis和Memcached都是內存數據庫,它們的訪問速度很是之快。但咱們在開發過程當中,這兩個內存數據庫,咱們到底要如何選擇呢?它們的優劣都有哪些?爲何如今看Redis要比Memcached更火一些?程序員
這篇文章,咱們就從各個方面來對比這兩個內存數據庫的差別,方便你在使用時,作出最符合業務須要的選擇。web
要分析它們的區別,主要從如下幾個方面對比:redis
-
線程模型 -
數據結構 -
淘汰策略 -
管道與事物 -
持久化 -
高可用 -
集羣化
總體比較
從以上幾個方面進行對比分析,總結以下表。算法
比較點 | Memcached | Redis |
---|---|---|
線程模型 | 多線程 | 單線程 |
數據結構 | 僅支持string、value最大1M、過時時間不能超過30天 | string、list、hash、set、zset、geo、hyperLogLog |
淘汰策略 | LRU | LRU、LFU、隨機等多種策略 |
管道與事物 | 不支持 | 支持 |
持久化 | 不支持 | 支持 |
高可用 | 不支持 | 主從複製+哨兵 |
集羣化 | 客戶端一致性哈希算法 | 主從複製+哨兵+固定哈希槽位 |
線程模型
要說性能,必需要分析它們的服務模型。spring
Memcached處理請求採用多線程模型,而且基於IO多路複用技術,主線程接收到請求後,分發給子線程處理。數據庫
這樣作好的好處是,當某個請求處理比較耗時,不會影響到其餘請求的處理。微信
固然,缺點是CPU的多線程切換必然存在性能損耗,同時,多線程在訪問共享資源時必然要加鎖,也會在必定程度上下降性能。網絡
Redis一樣採用IO多路複用技術,但它處理請求採用是單線程模型,從接收請求處處理數據都在一個線程中完成。數據結構
這意味着使用Redis,一旦某個請求處理耗時比較長,那麼整個Redis就會阻塞住,直到這個請求處理完成後返回,才能處理下一個請求,使用Redis時必定要避免複雜的耗時操做。多線程
單線程的好處是,少了CPU的上下文切換損耗,沒有了多線程訪問資源的鎖競爭,但缺點是沒法利用CPU多核的性能。
因爲Redis是內存數據庫,它的訪問速度很是地快,因此它的性能瓶頸不在於CPU,而在於內存和網絡帶寬,這也是做者採用單線程模型的主要緣由。同時,單線程對於程序開發很是友好,調試起來也很方便。開發多線程程序必然會增長必定的調試難度。
所以,當咱們的業務使用key的數據比較大時,Memcached的訪問性能要比Redis好一些。若是key的數據比較小,二者差異並不大。
嚴格來講,Redis的單線程指的是處理請求的線程,它自己還有其餘線程在工做,例若有其餘線程用來異步處理耗時的任務。
Redis6.0又進一步完善了多線程,在接收請求和發送請求時使用多線,進一步提升了處理性能。
數據結構
Memcached支持的數據結構很單一,僅支持string類型的操做。而且對於value的大小限制必須在1MB如下,過時時間不能超過30天。
而Redis支持的數據結構很是豐富,除了經常使用的數據類型string、list、hash、set、zset以外,還可使用geo、hyperLogLog數據類型。
使用Memcached時,咱們只能把數據序列化後寫入到Memcached中。而後再從Memcached中讀取數據,再反序列化爲咱們須要的格式,只能「整存整取」。
而Redis對於不一樣的數據結構能夠採用不一樣的操做方法,很是靈活。
-
list
:能夠方便的構建一個鏈表,或者看成隊列使用 -
hash
:靈活地操做咱們須要的字段,進行「整存零取」、「零存整取」以及「零存零取」 -
set
:構建一個不重複的集合,並方便地進行差集、並集運算 -
zset
:構建一個排行榜,或帶有權重的列表 -
geo
:用於地圖相關的業務,標識兩個地點的座標,以及計算它們的距離 -
hyperLogLog
:使用很是少的內存計算UV
總之,Redis正是由於提供了這麼豐富的數據結構,近幾年在內存數據庫領域大放異彩,爲咱們的業務開發提供了極大的便利。
淘汰策略
Memcached必須設置整個實例的內存上限,數據達到上限後觸發LRU淘汰機制,優先淘汰不經常使用使用的數據。
但它的數據淘汰機制存在一些問題:剛寫入的數據可能會被優先淘汰掉,這個問題主要是它自己內存管理設計機制致使的。
Redis沒有限制必須設置內存上限,若是內存足夠使用,Redis可使用足夠大的內存。
同時Redis提供了多種淘汰策略:
-
volatile-lru
:從過時key中按LRU機制淘汰 -
allkeys-lru
:在全部key中按LRU機制淘汰 -
volatile-random
:在過時key中隨機淘汰key -
allkeys-random
:在全部key中隨機淘汰key -
volatile-ttl
:優先淘汰最近要過時的key -
volatile-lfu
:在全部key中按LFU機制淘汰 -
allkeys-lfu
:在過時key中按LFU機制淘汰
咱們能夠針對業務場景,使用不一樣的數據淘汰策略。
管道與事物
Redis還支持管道功能,客戶端一次性打包發送多條命令到服務端,服務端依次處理客戶端發來的命令。這樣能夠減小來回往來的網絡IO次數,提供高訪問性能。
另外它還支持事物,這裏所說的事物並非MySQL那樣嚴格的事物模型,這種事物模型是Redis特有的。
通常事物會配合管道一塊使用,客戶端一次性打包發送多條命令到服務端,而且標識這些命令必須嚴格按順序執行,不能被其餘客戶端打斷。同時執行事務以前,客戶端能夠告訴服務端某個key稍後會進行相關操做,若是這個客戶端在操做這個key以前,有其餘客戶端對這個key進行更改,那麼當前客戶端在執行這些命令時會放棄整個事務操做,保證一致性。
持久化
Memcached不支持數據的持久化,若是Memcached服務宕機,那麼這個節點的數據將所有丟失。
Redis支持將數據持久化磁盤上,提供RDB和AOF兩種方式:
-
RDB
:將整個實例中的數據快照到磁盤上,全量持久化 -
AOF
:把每個寫命令持久到磁盤,增量持久化
Redis使用這兩種方式相互配合,完成數據完整性保障,最大程度下降服務宕機致使的數據丟失問題。
高可用
Memcached沒有主從複製架構,只能單節點部署,若是節點宕機,那麼該節點數據所有丟失。業務須要對這種狀況作兼容處理,當某個節點不可用時,把數據寫入到其餘節點以下降對業務的影響。
Redis擁有主從複製架構,兩個節點組成主從架構,從能夠實時同步主的數據,提升整個Redis服務的可用性。
同時Redis還提供了哨兵節點,在主節點宕機時,主動把從節點提高爲主節點,繼續提供服務。
主從兩個節點還能夠提供讀寫分離功能,進一步提升程序訪問的性能。
集羣化
Memcached和Redis都是由多個節點組成集羣對外提供服務,但他們的機制也有所不一樣。
Memcached的集羣化是在客戶端採用一致性哈希算法向指定節點發送數據,當一個節點宕機時,其餘節點會分擔這個節點的請求。
而Redis集羣化採用的是每一個節點維護一部分虛擬槽位,經過key的哈希計算,將key映射到具體的虛擬槽位上,這個槽位再映射到具體的Redis節點。
同時每一個Redis節點都包含至少一個從節點,組成主從架構,進一步提升每一個節點的高可用能力。
當增長或下線節點時,須要手動觸發數據遷移,從新進行哈希槽位映射。
Redis官方的集羣化解決方案爲Redis cluster,它採用無中心化的設計。另外也有第三方的採用中心化設計proxy方式的集羣化解決方案,例如Codis、Twemproxy。
後面我會專門針對Redis集羣化寫一些文章詳細介紹其內部的原理。
總結
總體來講,Redis提供了很是豐富的功能,並且性能基本上與Memcached相差無幾,這也是它最近這幾年佔領內存數據庫鰲頭的緣由。
若是你的業務須要各類數據結構給予支撐,同時要求數據的高可用保障,那麼選擇Redis是比較合適的。
若是你的業務很是簡單,只是簡單的set/get,而且對於內存使用並不高,那麼使用簡單的Memcached足夠。
來源於:http://kaito-kidd.com/2020/06/28/redis-vs-memcached/
關注微信公衆號:IT 老哥
回覆:Java實戰項目視頻教程:便可獲取200G,27套實戰項目視頻教程
回覆:Java 學習路線,便可獲取最新最全的一份學習路線圖
回覆:Java 電子書,便可領取 13 本頂級程序員必讀書籍
回覆:Java 全套教程,便可領取:Java 基礎、Java web、JavaEE 所有的教程,包括 spring boot 等
回覆:簡歷模板,便可獲取 100 份精美簡歷
本文分享自微信公衆號 - IT老哥(dys_family)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。