存儲原理(持久化)
- Mongo
Mongo的數據將會保存在底層文件系統,所以存儲容量遠大於redis和memcached。一個database中全部的collections以及索引信息會分散存儲在多個數據文件中,即mongodb並無像SQL數據庫那樣,每一個表的數據、索引分別存儲;數據分塊的單位爲extent(範圍,區域),即一個data file中有多個extents組成,extent中能夠保存collection數據或者indexes數據,一個extent只能保存同一個collection數據,不一樣的collections數據分佈在不一樣的extents中,indexes數據也保存在各自的extents中;最終,一個collection有一個或者多個extents構成,最小size爲8K,最大能夠爲2G,依次增大;它們分散在多個data files中。對於一個data file而言,可能包含多個collection的數據,即有多個不一樣collections的extents、index extents混合構成。每一個extent包含多條documents(或者index entries),每一個extent的大小可能不相等,但一個extent不會跨越2個data files。

-
Redis
一、Redis的數據存儲在內存中,同時能夠經過兩種存儲機制,將數據持久化到磁盤。
(1)Snapshot工做原理: 是將數據先存儲在內存,而後當數據累計達到某些設定的伐值的時候,就會觸發一次DUMP操做,將變化的數據一次性寫入數據文件(RDB文件)
(2)AOF 工做原理: 是將數據也是先存在內存,可是固定時候會使用調用fsync來完成對本次寫操做的日誌記錄,這個日誌揭露文件實際上是一個基於Redis網絡交互協議的文本文件。AOF調用fsync也不是說所有都是無阻塞的,在某些系統上可能出現fsync阻塞進程的狀況,對於這種狀況能夠經過配置修改,但默認狀況不要修改。AOF最關鍵的配置就是關於調用fsync追加日誌文件的頻率,有兩種預設頻率,always每次記錄進來都添加,everysecond 每秒添加一次。當redis重啓時,將會讀取AOF文件進行「重放」以恢復到redis關閉前的最後時刻。
(3)兩種存儲原理比較:html
a.性能
Snapshot方式的性能是要明顯高於AOF方式的,緣由有兩點:
採用2進制方式存儲數據,數據文件比較小,加載快速。存儲的時候是按照配置中的save策略來存儲,每次都是聚合不少數據批量存儲,寫入的效率很好,而AOF則通常都是工做在實時存儲或者準實時模式下。相對來講存儲的頻率高,效率卻偏低。
b.數據安全
AOF數據安全性高於Snapshot存儲,緣由:
Snapshot存儲是基於累計批量的思想,也就是說在容許的狀況下,累計的數據越多那麼寫入效率也就越高,但數據的累計是靠時間的積累完成的,那麼若是在長時間數據不寫入RDB,但Redis又遇到了崩潰,那麼沒有寫入的數據就沒法恢復了,可是AOF方式恰恰相反,根據AOF配置的存儲頻率的策略能夠作到最少的數據丟失和較高的數據恢復能力。
- Memcached
一、Memcached不支持內存數據的持久化操做,因此的數據都以in-momory的造成存儲。
數據類型:
- Mongo
一、字符串、整型、布爾型、雙進度浮點型...具體參照:http://www.yiibai.com/mongodb...
- Redis
一、除了簡單的key-value數據類型,同時還提供了list、hash、set、zset等數據結構的存儲
- Memcached
一、Memcached使用key-value形式存儲和訪問數據
網絡IO模型
- Mongo
一、多線程,同步 IO 模型。

由主線程進行 accept 鏈接,而後針對每個鏈接建立一個線程進行處理,「thread per connection」這種模型:
(1)不適合短鏈接服務,建立/刪除線程的開銷是巨大的,體如今建立線程時間和至少1MB 內存的使用。
(2)伸縮性受到線程數的限制,200+線程數的調度對 OS 也是不小的負擔。另外隨着線程數的增長, 因爲 mongo 自己業務的特性,對數據處理的併發度並不高,DB鎖和全局的原子操做形成的 context-switch 也是急劇上升,性能反而降低,頻繁的線程切換對於 cache 也不友好。
- Redis
一、Redis使用 單線程的IO複用模型 ,本身封裝了一個簡單的Ae_Event事件處理框架,主要實現了epoll、kqueue、kvport和select,對於單存只有IO操做來講,單線程能夠將速度優點發揮到最大,可是Redis也提供了一些簡單的計算功能,好比排序、聚合等,對於這些操做,單線程模型不能發揮多核CPU的優點,會嚴重影響總體吞吐率,由於在CPU的計算的過程當中,整個IO調度是被阻塞的,所以 Redis不適合用於計算。
- Memcached
一、Memcached是 多線程、非阻塞IO複用 的網絡模型,分爲監聽主線程和worker子線程,監聽線程監聽網絡鏈接,接受請求後,將鏈接描述字pipe傳遞給worker線程進行讀寫IO,網絡層使用libevent封裝的事件庫,多線程模型能夠發揮CPU多核做用,可是引入了cache coherency(緩存一致性)和鎖的問題,好比:Memcached最經常使用的stats命令,實際Memcached全部操做都要對這個全局變量加鎖、進行技術工做等,帶來了性能損耗。(緩存的一致性就是指緩存中的數據是否和目標存儲中的數據是同樣的,也就是說緩存中已經修改得數據是否已經保存到了物理存儲中,物理存儲中已經被修改得內容,是否與緩存的內容是同樣的。這就是一致性的概念。)
內存管理機制
- Redis
一、Redis的內存管理主要經過源碼中的zmalloc.h和zmalloc.c兩個文件來實現。Redis爲了方便內存的管理,在分配了一塊內存後,會將這塊內存的大小存入內存塊的頭部。以下圖所示,real_ptr是Redis調用malloc函數返回的指針,Redis將內存塊的大小size存入頭部(size所佔據的大小是已知的,爲size_t類型的長度),而後返回ret_ptr。當須要釋放內存的時候,ret_ptr別傳給內存管理程序,經過ret_ptr能夠很容易計算出real_ptr的值,而後將real_ptr傳給free釋放掉。
二、在Redis中,並非全部的數組都一直存儲在內存中的。這是和Memcached相比最大的一個區別。當物理內存用完的時候,Redis能夠將一些好久沒用到的value交換到磁盤(注:這裏用到的是Redis的Virtual Memory技術,Redis2.4版本以後已經不提倡使用了)。Redis只會緩存全部key的信息,若是Redis發現內存的使用量超過了某個閾值,將觸發swap操做。swap操做根據規則計算出哪些key對應的value須要swap到磁盤,而後再將這些key對應的value持久化到磁盤中,同時在內存中清除。這種特性使得Redis能夠保存超過其機器物理內存大小的數據。固然,機器自己的內存必需要可以保存全部的key,畢竟這部分數據是不會被swap到磁盤的。同時因爲Redis將內存中的數據swap到磁盤的時候,提供服務的主線程和進行swap的子線程會共享這部份內存,全部若是須要更新swap的數據,Redis將阻塞這個操做,直到子線程完成swap以後才能夠進行修改。當從Redis中讀取數據的時候,若是讀取的key的value不在內存中,那麼Redis須要從swap文件中加載對應的數據,而後再返回給client,這裏就存在一個I/O線程池的問題。在默認狀況下,Redis會出現阻塞,即完成全部的swap文件加載後纔會執行相應的操做。這種策略在client數量較小,進行批量操做的時候比較合適。可是若是Redis應用在一個大型的網站應用中,這顯示是沒法知足大併發的狀況的。因此Redis容許咱們設置I/O線程池的大小,對須要從swap文件中加載相應數據的讀取請求進行併發操做,減小阻塞的時間。redis
- Memcached
一、Memcached默認使用Slab Allocation機制來管理內存,它的主要思想是 按照預先規定的大小,將分配的內存分割成特定長度的塊,以存儲相應長度的key-value數據記錄,以徹底解決內存碎片的問題。Slab Allocation機制只爲存儲外部數據而設計,也就是說全部的key-value數據都存儲在slab allocation系統裏面,可是Memcached的其餘內存請求則是經過普通的malloc/free來申請,由於這些請求的數量和頻率決定了它們不會對整個系統的性能形成影響。
二、slab allocation機制的原理比較簡單,以下圖所示,它首先從操做系統申請一大塊內存,並將其分割成各類尺寸的chunk(塊),並把尺寸相同的chunk分紅一組組slab class。其中,chunk就是用來存儲key-value的最小單位。每一個slab class的大小,能夠在Memcached啓動的時候經過制定growth factor來控制。

三、當Memcached接收到客戶端發過來的數據時,會根據收到數據的大小選擇一個最合適的slab class,而後經過查詢Memcached保存着的該slab class內空閒chunk的列表,就能夠找到一個用於存儲數據的chunk。當一條數據記錄過時或者丟棄時,該記錄所佔用的chunk就能夠被回收,從新添加到空閒列表中。
四、從以上過程當中能夠看到,Memcached的內存管理效率高,而且不會形成內存碎片,可是它最大的不足是會形成空間浪費。由於每一個chunk都分配了特定長度的內存空間,因此變長數據沒法利用這些空間。以下圖所示,將100字節的數據緩存到128字節的chunk中,剩餘的28個字節就被浪費掉了。
算法
集羣管理
- Mongo
一、Replica Set:中文翻譯叫作副本集,就是集羣當中包含了多份數據,保證主節點掛掉了,備節點能繼續提供數據服務,提供的前提就是數據須要和主節點一致。以下圖:

二、Mongodb(M)表示主節點,Mongodb(S)表示備節點,Mongodb(A)表示仲裁節點。主備節點存儲數據,仲裁節點不存儲數據。客戶端同時鏈接主節點與備節點,不鏈接仲裁節點。
三、默認設置下,主節點提供全部增刪查改服務,備節點不提供任何服務。可是能夠經過設置使備節點提供查詢服務,這樣就能夠減小主節點的壓力,當客戶端進行數據查詢時,請求自動轉到備節點上。這個設置叫作Read Preference Modes,同時Java客戶端提供了簡單的配置方式,能夠沒必要直接對數據庫進行操做。
四、仲裁節點是一種特殊的節點,它自己並不存儲數據,主要的做用是決定哪個備節點在主節點掛掉以後提高爲主節點,因此客戶端不須要鏈接此節點。這裏雖然只有一個備節點,可是仍然須要一個仲裁節點來提高備節點級別(由備用節點提高爲主節點)。仲裁節點是必須的。詳見:http://blog.csdn.net/luonanqi...
- Redis
一、相比Memcached只能採用客戶端實現分佈式存儲,Redis更偏向在服務端構建分佈式存儲。新版本的Redis已經支持分佈式存儲功能。Redis Cluster是一個實現了分佈式而且容許單點故障的Redis高級版本,它沒有中心節點,具備線性可伸縮的功能。Redis Cluster的分佈式存儲架構,節點與節點之間經過二進制協議進行通信,節點與客戶端之間經過ascii協議通信。在數據的放置策略上,Redis Cluster將整個key的數值域劃分紅16384(2^14)個哈希槽,每一個節點上能夠存儲一個或多個哈希槽,也就是說Redis Cluster支持的最大節點數是16384。
二、爲了保證單點故障下得數據可用性,Redis Cluster引入了Master節點和Slave節點。在Redis Cluster中,每一個Master節點都會對應2個用於冗餘的Slave節點。這樣在整個集羣中,任意2個節點的宕機都不會致使數據的不可用。當Master節點下線後,集羣會自動選擇一個Slave節點成爲新的Master節點。
- Memcached
一、Memcached是全內存的數據緩衝系統,Redis雖然支持數據的持久化,可是全內存纔是其高性能的本質。做爲基於內存的存儲系統來講,機器物理內存的大小就是系統可以容納的最大數據量。若是數據超過了單臺機器的物理內存大小,那麼就須要構建集羣來擴展存儲能力。
二、Memcached自己並不支持分佈式,所以只能在客戶端經過像一致性哈希這樣的分佈式算法來實現Memcached的分佈式存儲。
應用場景
- Memcached及Redis
一、相對memcached來講,須要保證數據不丟失的話,選擇Redis。
二、固然,大部分狀況來講,選擇Redis是一個更好的選擇,由於它更強大、更受歡迎,而且比Memcached有更多的支持者。Memcached只是Redis功能中的一小部分。因此對於新項目來講,選擇Redis。
- Mongo
一、Mongo的使用和上面兩個數據庫是不衝突的,這篇文字只是作一個知識的總結。
二、日誌、消息記錄;不須要事務,不需複雜join鏈接表;須要大容量存儲;高吞吐量;數據不丟失;高可用;使用Mongo。
參考:
http://blog.csdn.net/sun49192...
https://www.zhihu.com/questio...
https://yq.aliyun.com/article...mongodb