爲何 Redis 要比 Memcached 更火?

做者:Kaito
連接:kaito-kidd.com/2020/06/28/redis-vs-memcached/

前言

咱們都知道,Redis和Memcached都是內存數據庫,它們的訪問速度很是之快。但咱們在開發過程當中,這兩個內存數據庫,咱們到底要如何選擇呢?它們的優劣都有哪些?java

爲何如今看Redis要比Memcached更火一些?redis

這篇文章,咱們就從各個方面來對比這兩個內存數據庫的差別,方便你在使用時,作出最符合業務須要的選擇。算法

要分析它們的區別,主要從如下幾個方面對比:spring

  • 線程模型
  • 數據結構
  • 淘汰策略
  • 管道與事務
  • 持久化
  • 高可用
  • 集羣化

線程模型

要說性能,必需要分析它們的服務模型。數據庫

Memcached處理請求採用多線程模型,而且基於IO多路複用技術,主線程接收到請求後,分發給子線程處理。網絡

這樣作好的好處是,當某個請求處理比較耗時,不會影響到其餘請求的處理。數據結構

固然,缺點是CPU的多線程切換必然存在性能損耗,同時,多線程在訪問共享資源時必然要加鎖,也會在必定程度上下降性能。多線程

Redis一樣採用IO多路複用技術,但它處理請求採用是單線程模型,從接收請求處處理數據都在一個線程中完成。推薦看一下這篇《Redis 究竟是單線程仍是多線程?》架構

這意味着使用Redis,一旦某個請求處理耗時比較長,那麼整個Redis就會阻塞住,直到這個請求處理完成後返回,才能處理下一個請求,使用Redis時必定要避免複雜的耗時操做。intellij-idea

單線程的好處是,少了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正是由於提供了這麼豐富的數據結構,近幾年在內存數據庫領域大放異彩,爲咱們的業務開發提供了極大的便利。關注公衆號Java技術棧獲取更多數據類型的詳細使用教程。

淘汰策略

Memcached必須設置整個實例的內存上限,數據達到上限後觸發LRU淘汰機制,優先淘汰不經常使用使用的數據。

但它的數據淘汰機制存在一些問題:剛寫入的數據可能會被優先淘汰掉,這個問題主要是它自己內存管理設計機制致使的。

Redis沒有限制必須設置內存上限,若是內存足夠使用,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還提供了哨兵節點,在主節點宕機時,主動把從節點提高爲主節點,繼續提供服務。Redis哨兵如何與Spring Boot集成等系列教程能夠關注公衆號Java技術棧搜索閱讀。

主從兩個節點還能夠提供讀寫分離功能,進一步提升程序訪問的性能。

集羣化

Memcached和Redis都是由多個節點組成集羣對外提供服務,但他們的機制也有所不一樣。

Memcached的集羣化是在客戶端採用一致性哈希算法向指定節點發送數據,當一個節點宕機時,其餘節點會分擔這個節點的請求。

而Redis集羣化採用的是每一個節點維護一部分虛擬槽位,經過key的哈希計算,將key映射到具體的虛擬槽位上,這個槽位再映射到具體的Redis節點。

同時每一個Redis節點都包含至少一個從節點,組成主從架構,進一步提升每一個節點的高可用能力。

當增長或下線節點時,須要手動觸發數據遷移,從新進行哈希槽位映射。

Redis官方的集羣化解決方案爲Redis cluster,它採用無中心化的設計。另外也有第三方的採用中心化設計proxy方式的集羣化解決方案,例如Codis、Twemproxy。

總結

從以上幾個方面進行對比分析,總結以下表。

總體來講,Redis提供了很是豐富的功能,並且性能基本上與Memcached相差無幾,這也是它最近這幾年佔領內存數據庫鰲頭的緣由。

若是你的業務須要各類數據結構給予支撐,同時要求數據的高可用保障,那麼選擇Redis是比較合適的。

若是你的業務很是簡單,只是簡單的set/get,而且對於內存使用並不高,那麼使用簡單的Memcached足夠。

若是此文章能給您帶來小小的工做效率提高,不妨在看、轉發一下,以鼓勵我寫出更好的文章!

近期熱文推薦:

1.免費獲取 IntelliJ IDEA 激活碼的 6 種方式!

2.我用 Java 8 寫了一段邏輯,同事直呼看不懂,你試試看。。

3.吊打 Tomcat ,Undertow 性能很炸!!

4.國人開源了一款超好用的 Redis 客戶端,真香!!

5.《Java開發手冊(嵩山版)》最新發布,速速下載!

以爲不錯,別忘了隨手點贊+轉發哦!

相關文章
相關標籤/搜索