Redis、memcache、MongoDB 對比

2020-08-07 11:41:18

一、Redis簡介

  redis是一個key-value儲存系統。和Memcached類似,它支援儲存的value型別相對更多,包括string(字串)、list(鏈表)、set(集合)、zset(sorted set --有序集合)和hash(雜湊型別)。這些數據型別都支援push/pop、add/remove及取交集並集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎上,redis支援各種不同方式的排序。與memcached一樣,爲了保證效率,數據都是快取在記憶體中。區別的是redis會週期性的把更新的數據寫入磁碟或者把修改操作寫入追加的記錄檔案,並且在此基礎上實現了master-slave(主從)同步。
  Redis 是一個高效能的key-value數據庫。 redis的出現,很大程度補償了memcached這類key/value儲存的不足,在部 分場合可以對關係數據庫起到很好的補充作用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等用戶端,使用很方便。
  Redis支援主從同步。數據可以從主伺服器向任意數量的從伺服器上同步,從伺服器可以是關聯其他從伺服器的主伺服器。這使得Redis可執行單層樹複製。存檔可以有意無意的對數據進行寫操作。由於完全實現了發佈/訂閱機制 機製,使得從數據庫在任何地方同步樹時,可訂閱一個頻道並接收主伺服器完整的訊息發佈記錄。同步對讀取操作的可延伸性和數據冗餘很有幫助。
  是一個完全開源免費的 key-value 記憶體數據庫 。通常被認爲是一個數據結構伺服器,主要是因爲其有着豐富的數據結構 strings、map、 list、sets、 sorted sets。

  • Redis 使用最佳方式是全部數據 in-memory。
  • Redis 更多場景是作爲 Memcached 的替代者來使用。
  • 當需要除 key/value 之外的更多數據型別支援時,使用 Redis 更合適。
  • 當儲存的數據不能被剔除時,使用 Redis 更合適。

Redis(管道,雜湊):

  • Redis 不僅僅支援簡單的 k/v 型別的數據,同時還提供 list,set,zset,hash 等數據結構的儲存。
  • Redis 支援數據的備份,即 master-slave 模式的數據備份。
  • Redis 支援數據的持久化,可以將記憶體中的數據保持在磁碟中,重新啓動的時候可以再次載入進行使用。

二、Redis 實現原理或機制 機製

  Redis 是一個 key-value 儲存系統。和 Memcached 類似,但是解決了斷電後數據完全丟失的情況,而且她支援更多元化的 value 型別,除了和 string 外,還支援lists(鏈表)、sets(集合)和 zsets(有序集合)幾種數據型別。這些數據型別都支援 push/pop、add/remove 及取交集並集和差集及更豐富的操作,而且這些操作都是原子性的。
Redis 是一種基於用戶端 - 伺服器端模型以及請求 / 響應協定的 TCP 服務。這意味着通常情況下一個請求會遵循以下步驟:

  • 用戶端向伺服器端發送一個查詢請求,並監聽 Socket 返回,通常是以阻塞模式,等待
  • 伺服器端響應。伺服器端處理命令,並將結果返回給用戶端。
  • 在伺服器端未響應時,用戶端可以繼續向伺服器端發送請求,並最終一次性讀取所有伺服器端的響應。

Redis 管道技術最顯著的優勢是提高了 Redis 服務的效能。

分割區是分割數據到多個 Redis 範例的處理過程,因此每個範例只儲存 key 的一個子集。
Redis 有兩種型別分割區:

  • 最簡單的分割區方式是按範圍分割區,就是對映一定範圍的物件到特定的 Redis 範例。比如,ID 從 0 到 10000 的使用者會儲存到範例 R0,ID 從 10001 到 20000 的使用者會儲存到 R1,以此類推。
    這種方式是可行的,並且在實際中使用,不足就是要有一個區間範圍到範例的對映表。這個表要被管理,同時還需要各 種物件的對映表,通常對 Redis 來說並非是好的方法。
  • 雜湊分割區:另外一種分割區方法是 hash 分割區。這對任何 key 都適用,也無需是object_name: 這種形式,像下面 下麪描述的一樣簡單:用一個 hash 函數將 key 轉換爲一個數字,比如使用 crc32 hash 函數。對 keyfoobar 執行 crc32(foobar) 會輸出類似 93024922 的整數。
    對這個整數取模,將其轉化爲 0-3 之間的數位,就可以將這個整數對映到 4 個Redis 範例中的一個了。93024922 % 4 = 2,就是說 key foobar 應該被存到 R2範例中。注意:取模操作是取除的餘數,通常在多種程式語言中用 % 操作符實現。

三、Redis叢集模式存在的問題

3.1 擴容問題

  因爲使用了一致性雜湊進行分片,那麼不同的 key 分佈到不同的 Redis Server 上,當我們需要擴容時,需要增加機器到分片列表中,這時候會使得同樣的 key 算出來落到跟原來不同的機器上,這樣如果要取某一個值,會出現取不到的情況,對於這種情況,Redis 的作者提出了一種名爲 Pre-Sharding 的方式:Pre-Sharding 方法是將每一個台物理機上,執行多個不同埠的 Redis 範例,假如有三個物理機,每個物理機執行三個 Redis 範例,那麼我們的分片列表中實際有 9 個 Redis 範例,當我們需要擴容時,增加一臺物理機,步驟如下:

  1. 在新的物理機上執行 Redis-Server;
  2. 該 Redis-Server 從屬於 (slaveof) 分片列表中的某一 Redis-Server(假設叫 RedisA);
  3. 等主從複製 (Replication) 完成後,將用戶端分片列表中 RedisA 的IP 和埠改爲新物理機上 Redis-Server 的 IP 和埠;
  4. 停止 RedisA。這樣相當於將某一 Redis-Server 轉移到了一臺新機器上。Prd-Sharding 實際上是一種線上擴容的辦法,但還是很依賴 Redis 本身的複製功能的,如果主庫快照數據檔案過大,這個複製的過程也會很久,同時會給主庫帶來壓力。所以做這個拆分的過程最好選擇爲業務存取低峯時段進行。

3.2 單點故障問題

  還是用到 Redis 主從複製的功能,兩臺物理主機上分別都執行有Redis Server,其中一個 Redis-Server 是另一個的從庫,採用雙機熱備技術,用戶端通過虛擬 IP 存取主庫的物理 IP,當主庫宕機時,切換到從庫的物理 IP。只是事後修復主庫時,應該將之前的從庫改爲主庫(使用命令 slaveof noone),主庫變爲其從庫(使命令 slaveof IP PORT),這樣才能 纔能保證修復期間新增數據的一致性。

3.3 Redis 有什麼用?

  1. 速度快:使用標準 C 寫,所有數據都在記憶體中完成,讀寫速度分別達到 10萬 / 20 萬。
  2. 持久化:對數據的更新採用 Copy-on-write 技術,可以非同步地儲存到磁碟上,主要有兩種策略,一是根據時間,更新次數的快照(save 300 10 )二是基於語句追加方式 (Append-only file,aof) 。
  3. 自動操作:對不同數據型別的操作都是自動的,很安全。
  4. 快速的主 – 從複製,官方提供了一個數據,Slave 在 21 秒即完成了對Amazon 網站 10G key set 的複製。
  5. Sharding 技術: 很容易將數據分佈到多個 Redis 範例中,數據庫的擴充套件是個永恆的話題,在關係型數據庫中,主要是以新增硬體、以分割區爲主要技術形式的縱向擴充套件解決了很多的應用場景,但隨着 web2.0、行動網際網路、雲端計算等應用的興起,這種擴充套件模式已經不太適合了,所以近年來,像採用主從設定、數據庫複製形式的,Sharding 這種技術把負載分佈到多個特理節點上去的橫向擴充套件方式用處越來越多。

3.4 小結

  1. 提高了 DB 的可延伸性,只需要將新加的數據放到新加的伺服器上就可以了
  2. 提高了 DB 的可用性,隻影響到需要存取的 shard 伺服器上的數據的使用者
  3. 提高了 DB 的可維護性,對系統的升級和設定可以按 shard 一個個來搞,對服務產生的影響較小
  4. 小的數據庫存的查詢壓力小,查詢更快,效能更好

四、MongoDB簡介

  MongoDB 是一個基於分佈式檔案儲存的數據庫。由 C++ 語言編寫。旨在爲 WEB 應用提供可延伸的高效能數據儲存解決方案。
  MongoDB是一個介於關係數據庫和非關係數據庫之間的產品,是非關係數據庫當中功能最豐富,最像關係數據庫的。它支援的數據結構非常鬆散,是類似json的bson格式,因此可以儲存比較複雜的數據型別。Mongo最大的特點是它支援的查詢語言非常強大,其語法有點類似於物件導向的查詢語言,幾乎可以實現類似關係數據庫單表查詢的絕大部分功能,而且還支援對數據建立索引。
  非關係型數據庫 (NoSql),Mongo DB 很好的實現了物件導向的思想 (OO 思想), 在Mongo DB 中 每一條記錄都是一個 Document 物件。Mongo DB 最大的優勢在於所有的數據持久操作都無需開發人員手動編寫 SQL 語句, 直接呼叫方法就可以輕鬆的實現 CRUD 操作.

4.1 MongoDB 的特點

  • 高效能、易部署、易使用,儲存數據非常方便。主要功能特性有:
  • 面向集合儲存,易儲存物件型別的數據。
  • 模式自由。
  • 支援動態查詢。
  • 支援完全索引,包含內部物件。
  • 支援查詢。
  • 支援複製和故障恢復。
  • 使用高效的二進制數據儲存,包括大型物件(如視訊等)。
  • 自動處理碎片,以支援雲端計算層次的擴充套件性
  • 支援 Python,PHP,Ruby,Java,C,C#,Javascript,Perl 及 C++ 語言的驅動程式,社羣中也提供了對 Erlang 及. NET 等平臺的驅動程式。
  • 檔案儲存格式爲 BSON(一種 JSON 的擴充套件)。
  • 可通過網路存取。

4.2 MongoDB 的功能

  • 面向集合的儲存:適合儲存物件及 JSON 形式的數據。
  • 動態查詢:Mongo 支援豐富的查詢表達式。查詢指令使用 JSON 形式的標記,可輕易查詢文件中內嵌的物件及陣列。
  • 完整的索引支援:包括文件內嵌物件及陣列。Mongo 的查詢優化器會分析查詢表達式,並生成一個高效的查詢計劃。
  • 查詢監視:Mongo 包含一個監視工具用於分析數據庫操作的效能。
  • 複製及自動故障轉移:Mongo 數據庫支援伺服器之間的數據複製,支援主 - 從模式及伺服器之間的相互複製。複製的主要目標是提供冗餘及自動故障轉移。
  • 高效的傳統儲存方式:支援二進制數據及大型物件(如照片或圖片)
  • 自動分片以支援雲級別的伸縮性:自動分片功能支援水平的數據庫叢集,可動態新增額外的機器。

4.3 MongoDB 的適用場景

  • 網站數據:Mongo 非常適合實時的插入,更新與查詢,並具備網站實時數據儲存所需的複製及高度伸縮性。
  • 快取:由於效能很高,Mongo 也適合作爲資訊基礎設施的快取層。在系統重新啓動之後,由 Mongo 搭建的持久化快取層可以避免下層的數據源 過載。
  • 大尺寸,低價值的數據:使用傳統的關係型數據庫儲存一些數據時可能會比較昂貴,在此之前,很多時候程式設計師往往會選擇傳統的檔案進行儲存。
  • 高伸縮性的場景:Mongo 非常適合由數十或數百台伺服器組成的數據庫。Mongo的路線圖中已經包含對 MapReduce 引擎的內建支援。
  • 用於物件及 JSON 數據的儲存:Mongo 的 BSON 數據格式非常適合文件化格式的儲存及查詢。

五、Redis、memcache、MongoDB 對比

   mongodb 和 memcached 不是一個範疇內的東西。mongodb 是文件型的非關係型數據庫,其優勢在於查詢功能比較強大,能儲存海量數據。和 memcached 更爲接近的是 Redis。它們都是記憶體型數據庫,數據儲存在記憶體中,通過 tcp 直接存取,優勢是速度快,併發高,缺點是數據型別有限,查詢功能不強,一般用作快取。

5.1 效能

Redis 和 memcache 差不多,要大於 mongodb。

5.2 操作的便利性

  • memcache 數據結構單一。
  • Redis 豐富一些,數據操作方面,Redis 更好一些,較少的網路 IO 次數。
  • mongodb 支援豐富的數據表達,索引,最類似關係型數據庫,支援的查詢語言非常豐富。

5.3 記憶體空間的大小和數據量的大小

  • Redis 在 2.0 版本後增加了自己的 VM 特性,突破實體記憶體的限制;可以對key value 設定過期時間(類似 memcache)。
  • memcache 可以修改最大可用記憶體, 採用 LRU 演算法。
  • mongoDB 適合大數據量的儲存,依賴操作系統 VM 做記憶體管理,吃記憶體也比較厲害,服務不要和別的服務在一起。

5.4 可用性(單點問題)

  • Redis 對於單點問題,依賴用戶端來實現分佈式讀寫;主從複製時,每次從節點重新連線主節點都要依賴整個快照, 無增量複製,因效能和效率問題,所以單點問題比較複雜;不支援自動 sharding, 需要依賴程式設定一致 hash 機制 機製。一種替代方案是,不用 Redis 本身的複製機制 機製,採用自己做主動複製(多份儲存),或者改成增量複製的方式(需要自己實現),一致性問題和效能的權衡。
  • Memcache 本身沒有數據冗餘機制 機製,也沒必要;對於故障預防,採用依賴成熟的 hash 或者環狀的演算法,解決單點故障引起的抖動問題。
  • mongoDB 支援 master-slave,replicaset(內部採用 paxos 選舉演算法,自動故障恢復),auto sharding 機制 機製,對用戶端遮蔽了故障轉移和切分機制 機製。

5.5 可靠性(持久化)

  • 對於數據持久化和數據恢復,Redis 支援(快照、AOF):依賴快照進行持久化,aof 增強了可靠性的同時,對效能有所影響。
  • memcache 不支援,通常用在做快取, 提升效能;
  • MongoDB 從 1.8 版本開始採用 binlog 方式支援持久化的可靠性。

5.6 數據一致性(事務支援)

  • Memcache 在併發場景下,用 cas 保證一致性。
  • Redis 事務支援比較弱,只能保證事務中的每個操作連續執行。
  • mongoDB 不支援事務。

5.7 數據分析

mongoDB 內建了數據分析的功能 (mapreduce), 其他不支援。

5.8 應用場景

  • Redis:數據量較小的更效能操作和運算上。
  • memcache:用於在動態系統中減少數據庫負載,提升效能; 做快取,提高效能(適合讀多寫少,對於數據量比較大,可以採用 sharding)。
  • MongoDB: 主要解決海量數據的存取效率問題。