存放緩存的三種方式 Redis、Memcache和MongoDB的區別


>>Memcached

Memcached的優點:
Memcached可以利用多核優勢,單實例吞吐量極高,可以達到幾十萬QPS(取決於key、value的字節大小以及服務器硬件性能,日常環境中QPS高峰大約在4-6w左右)。適用於最大程度扛量。
支持直接配置為session handle。
Memcached的局限性:
只支持簡單的key/value數據結構,不像Redis可以支持豐富的數據類型。
無法進行持久化,數據不能備份,只能用於緩存使用,且重啟后數據全部丟失。
無法進行數據同步,不能將MC中的數據遷移到其他MC實例中。
Memcached內存分配采用Slab Allocation機制管理內存,value大小分布差異較大時會造成內存利用率降低,並引發低利用率時依然出現踢出等問題。需要用戶注重value設計。

>>Redis

Redis的優點:
支持多種數據結構,如 string(字符串)、 list(雙向鏈表)、dict(hash表)、set(集合)、zset(排序set)、hyperloglog(基數估算)
支持持久化操作,可以進行aof及rdb數據持久化到磁盤,從而進行數據備份或數據恢復等操作,較好的防止數據丟失的手段。
支持通過Replication進行數據復制,通過master-slave機制,可以實時進行數據的同步復制,支持多級復制和增量復制,master-slave機制是Redis進行HA的重要手段。
單線程請求,所有命令串行執行,並發情況下不需要考慮數據一致性問題。
支持pub/sub消息訂閱機制,可以用來進行消息訂閱與通知
支持簡單的事務需求,但業界使用場景很少,並不成熟。

Redis的局限性:
Redis只能使用單線程,性能受限於CPU性能,故單實例CPU最高才可能達到5-6wQPS每秒(取決於數據結構,數據大小以及服務器硬件性能,日常環境中QPS高峰大約在1-2w左右)。
支持簡單的事務需求,但業界使用場景很少,並不成熟,既是優點也是缺點。
Redis在string類型上會消耗較多內存,可以使用dict(hash表)壓縮存儲以降低內存耗用。

Mc和Redis都是Key-Value類型,不適合在不同數據集之間建立關系,也不適合進行查詢搜索。比如redis的keys pattern這種匹配操作,對redis的性能是災難。

>>mongoDB 

mongoDB 是一種文檔性的數據庫。先解釋一下文檔的數據庫,即可以存放xml、json、bson類型系那個的數據。

這些數據具備自述性(self-describing),呈現分層的樹狀數據結構。redis可以用hash存放簡單關系型數據。

mongoDB 存放json格式數據。

適合場景:事件記錄、內容管理或者博客平台,比如評論系統。

1.mongodb持久化原理

mongodb與mysql不同,mysql的每一次更新操作都會直接寫入硬盤,但是mongo不會,做為內存型數據庫,數據操作會先寫入內存,然后再會持久化到硬盤中去,那么mongo是如何持久化的呢
mongodb在啟動時,專門初始化一個線程不斷循環(除非應用crash掉),用於在一定時間周期內來從defer隊列中獲取要持久化的數據並寫入到磁盤的journal(日志)和mongofile(數據)處,當然因為它不是在用戶添加記錄時就寫到磁盤上,所以按mongodb開發者說,它不會造成性能上的損耗,因為看過代碼發現,當進行CUD操作時,記錄(Record類型)都被放入到defer隊列中以供延時批量(groupcommit)提交寫入,但相信其中時間周期參數是個要認真考量的參數,系統為90毫秒,如果該值更低的話,可能會造成頻繁磁盤操作,過高又會造成系統宕機時數據丟失過。

2.什么是NoSQL數據庫?NoSQL和RDBMS有什么區別?在哪些情況下使用和不使用NoSQL數據庫?
NoSQL是非關系型數據庫,NoSQL = Not Only SQL。
關系型數據庫采用的結構化的數據,NoSQL采用的是鍵值對的方式存儲數據。
在處理非結構化/半結構化的大數據時;在水平方向上進行擴展時;隨時應對動態增加的數據項時可以優先考慮使用NoSQL數據庫。
在考慮數據庫的成熟度;支持;分析和商業智能;管理及專業性等問題時,應優先考慮關系型數據庫。

3.MySQL和MongoDB之間最基本的區別是什么?
關系型數據庫與非關系型數據庫的區別,即數據存儲結構的不同

4.MongoDB的特點是什么?
(1)面向文檔(2)高性能(3)高可用(4)易擴展(5)豐富的查詢語言

5.MongoDB支持存儲過程嗎?如果支持的話,怎么用?
MongoDB支持存儲過程,它是javascript寫的,保存在db.system.js表中。

6.如何理解MongoDB中的GridFS機制,MongoDB為何使用GridFS來存儲文件?
GridFS是一種將大型文件存儲在MongoDB中的文件規范。使用GridFS可以將大文件分隔成多個小文檔存放,這樣我們能夠有效的保存大文檔,而且解決了BSON對象有限制的問題。

7.為什么MongoDB的數據文件很大?
MongoDB采用的預分配空間的方式來防止文件碎片。

8.當更新一個正在被遷移的塊(Chunk)上的文檔時會發生什么?
更新操作會立即發生在舊的塊(Chunk)上,然后更改才會在所有權轉移前復制到新的分片上。

9.MongoDB在A:{B,C}上建立索引,查詢A:{B,C}和A:{C,B}都會使用索引嗎?
不會,只會在A:{B,C}上使用索引。

10.如果一個分片(Shard)停止或很慢的時候,發起一個查詢會怎樣?
如果一個分片停止了,除非查詢設置了“Partial”選項,否則查詢會返回一個錯誤。如果一個分片響應很慢,MongoDB會等待它的響應。

>>Redis、Memcache和MongoDB的區別

從以下幾個維度,對redis、memcache、mongoDB 做了對比,

1、性能

都比較高,性能對我們來說應該都不是瓶頸

總體來講,TPS方面redis和memcache差不多,要大於mongodb

2、操作的便利性

memcache數據結構單一

redis豐富一些,數據操作方面,redis更好一些,較少的網絡IO次數

mongodb支持豐富的數據表達,索引,最類似關系型數據庫,支持的查詢語言非常豐富

3、內存空間的大小和數據量的大小

redis在2.0版本后增加了自己的VM特性,突破物理內存的限制;可以對key value設置過期時間(類似memcache)

memcache可以修改最大可用內存,采用LRU算法

mongoDB適合大數據量的存儲,依賴操作系統VM做內存管理,吃內存也比較厲害,服務不要和別的服務在一起

4、可用性(單點問題)

對於單點問題,

redis,依賴客戶端來實現分布式讀寫;主從復制時,每次從節點重新連接主節點都要依賴整個快照,無增量復制,因性能和效率問題,

所以單點問題比較復雜;不支持自動sharding,需要依賴程序設定一致hash 機制。

一種替代方案是,不用redis本身的復制機制,采用自己做主動復制(多份存儲),或者改成增量復制的方式(需要自己實現),一致性問題和性能的權衡

Memcache本身沒有數據冗余機制,也沒必要;對於故障預防,采用依賴成熟的hash或者環狀的算法,解決單點故障引起的抖動問題。

mongoDB支持master-slave,replicaset(內部采用paxos選舉算法,自動故障恢復),auto sharding機制,對客戶端屏蔽了故障轉移和切分機制。

5、可靠性(持久化)

對於數據持久化和數據恢復,

redis支持(快照、AOF):依賴快照進行持久化,aof增強了可靠性的同時,對性能有所影響

memcache不支持,通常用在做緩存,提升性能;

MongoDB從1.8版本開始采用binlog方式支持持久化的可靠性

6、數據一致性(事務支持)

Memcache 在並發場景下,用cas保證一致性

redis事務支持比較弱,只能保證事務中的每個操作連續執行

mongoDB不支持事務

7、數據分析

mongoDB內置了數據分析的功能(mapreduce),其他不支持

8、應用場景

redis:數據量較小的更性能操作和運算上

【Redis應用場景】

1、熱點數據的緩存

由於redis訪問速度塊、支持的數據類型比較豐富,所以redis很適合用來存儲熱點數據,另外結合expire,我們可以設置過期時間然后再進行緩存更新操作,這個功能最為常見,我們幾乎所有的項目都有所運用。

2、限時業務的運用

redis中可以使用expire命令設置一個鍵的生存時間,到時間后redis會刪除它。利用這一特性可以運用在限時的優惠活動信息、手機驗證碼等業務場景。

3、計數器相關問題

redis由於incrby命令可以實現原子性的遞增,所以可以運用於高並發的秒殺活動、分布式序列號的生成、具體業務還體現在比如限制一個手機號發多少條短信、一個接口一分鍾限制多少請求、一個接口一天限制調用多少次等等。

4、排行榜相關問題

關系型數據庫在排行榜方面查詢速度普遍偏慢,所以可以借助redis的SortedSet進行熱點數據的排序。

在奶茶活動中,我們需要展示各個部門的點贊排行榜, 所以我針對每個部門做了一個SortedSet,然后以用戶的openid作為上面的username,以用戶的點贊數作為上面的score, 然后針對每個用戶做一個hash,通過zrangebyscore就可以按照點贊數獲取排行榜,然后再根據username獲取用戶的hash信息,這個當時在實際運用中性能體驗也蠻不錯的。

  5、分布式鎖

這個主要利用redis的setnx命令進行,setnx:"set if not exists"就是如果不存在則成功設置緩存同時返回1,否則返回0 ,這個特性在俞你奔遠方的后台中有所運用,因為我們服務器是集群的,定時任務可能在兩台機器上都會運行,所以在定時任務中首先 通過setnx設置一個lock,如果成功設置則執行,如果沒有成功設置,則表明該定時任務已執行。 當然結合具體業務,我們可以給這個lock加一個過期時間,比如說30分鍾執行一次的定時任務,那么這個過期時間設置為小於30分鍾的一個時間 就可以,這個與定時任務的周期以及定時任務執行消耗時間相關。

當然我們可以將這個特性運用於其他需要分布式鎖的場景中,結合過期時間主要是防止死鎖的出現。

6、延時操作

這個目前我做過相關測試,但是還沒有運用到我們的實際項目中,下面我舉個該特性的應用場景。 比如在訂單生產后我們占用了庫存,10分鍾后去檢驗用戶是夠真正購買,如果沒有購買將該單據設置無效,同時還原庫存。 由於redis自2.8.0之后版本提供Keyspace Notifications功能,允許客戶訂閱Pub/Sub頻道,以便以某種方式接收影響Redis數據集的事件。 所以我們對於上面的需求就可以用以下解決方案,我們在訂單生產時,設置一個key,同時設置10分鍾后過期, 我們在后台實現一個監聽器,監聽key的實效,監聽到key失效時將后續邏輯加上。 當然我們也可以利用rabbitmq、activemq等消息中間件的延遲隊列服務實現該需求。

7、分頁、模糊搜索

redis的set集合中提供了一個zrangebylex方法,語法如下:

ZRANGEBYLEX key min max [LIMIT offset count]

通過ZRANGEBYLEX zset - + LIMIT 0 10 可以進行分頁數據查詢,其中- +表示獲取全部數據

zrangebylex key min max 這個就可以返回字典區間的數據,利用這個特性可以進行模糊查詢功能,這個也是目前我在redis中發現的唯一一個支持對存儲內容進行模糊查詢的特性。

前幾天我通過這個特性,對學校數據進行了模擬測試,學校數據60萬左右,響應時間在700ms左右,比mysql的like查詢稍微快一點,但是由於它可以避免大量的數據庫io操作,所以總體還是比直接mysql查詢更利於系統的性能保障。

 

8、點贊、好友等相互關系的存儲

Redis set對外提供的功能與list類似是一個列表的功能,特殊之處在於set是可以自動排重的,當你需要存儲一個列表數據,又不希望出現重復數據時,set是一個很好的選擇,並且set提供了判斷某個成員是否在一個set集合內的重要接口,這個也是list所不能提供的。 又或者在微博應用中,每個用戶關注的人存在一個集合中,就很容易實現求兩個人的共同好友功能。

這個在奶茶活動中有運用,就是利用set存儲用戶之間的點贊關聯的,另外在點贊前判斷是否點贊過就利用了sismember方法,當時這個接口的響應時間控制在10毫秒內,十分高效。

9、隊列

由於redis有list push和list pop這樣的命令,所以能夠很方便的執行隊列操作。

 

redis已經逐漸取代了memcached,成為分布式場景廣泛使用的緩存方案。

 

memcache:用於在動態系統中減少數據庫負載,提升性能;做緩存,提高性能(適合讀多寫少,對於數據量比較大,可以采用sharding)

MongoDB:主要目標是在鍵/值存儲方式(提供了高性能和高度伸縮性)和傳統的RDBMS 系統(具有豐富的功能)之間架起一座橋梁,它集兩者的優勢於一身。根據官方網站的描述,Mongo 適用於以下場景。

【MongoDB應用場景】

1、 網站數據:Mongo 非常適合實時的插入,更新與查詢,並具備網站實時數據存儲所需的復制及高度伸縮性。
2、緩存:由於性能很高,Mongo 也適合作為信息基礎設施的緩存層。在系統重啟之后,由Mongo 搭建的持久化緩存層可以避免下層的數據源過載。
3、 大尺寸、低價值的數據:使用傳統的關系型數據庫存儲一些數據時可能會比較昂貴,在此之前,很多時候程序員往往會選擇傳統的文件進行存儲。
4、 高伸縮性的場景:Mongo 非常適合由數十或數百台服務器組成的數據庫,Mongo 的路線圖中已經包含對MapReduce 引擎的內置支持。
5、用於對象及JSON 數據的存儲:Mongo 的BSON 數據格式非常適合文檔化格式的存儲及查詢。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM