存儲原理(持久化)
-
Mongo
Mongo的數(shù)據(jù)將會保存在底層文件系統(tǒng),因此存儲容量遠(yuǎn)大于redis和memcached韵吨。一個database中所有的collections以及索引信息會分散存儲在多個數(shù)據(jù)文件中匿垄,即mongodb并沒有像SQL數(shù)據(jù)庫那樣,每個表的數(shù)據(jù)归粉、索引分別存儲椿疗;數(shù)據(jù)分塊的單位為extent(范圍,區(qū)域)糠悼,即一個data file中有多個extents組成届榄,extent中可以保存collection數(shù)據(jù)或者indexes數(shù)據(jù),一個extent只能保存同一個collection數(shù)據(jù)倔喂,不同的collections數(shù)據(jù)分布在不同的extents中铝条,indexes數(shù)據(jù)也保存在各自的extents中;最終席噩,一個collection有一個或者多個extents構(gòu)成班缰,最小size為8K,最大可以為2G班挖,依次增大鲁捏;它們分散在多個data files中。對于一個data file而言,可能包含多個collection的數(shù)據(jù)给梅,即有多個不同collections的extents假丧、index extents混合構(gòu)成。每個extent包含多條documents(或者index entries)动羽,每個extent的大小可能不相等包帚,但一個extent不會跨越2個data files。
image.png
-
Redis
1运吓、Redis的數(shù)據(jù)存儲在內(nèi)存中渴邦,同時可以通過兩種存儲機(jī)制,將數(shù)據(jù)持久化到磁盤拘哨。
(1)Snapshot工作原理: 是將數(shù)據(jù)先存儲在內(nèi)存谋梭,然后當(dāng)數(shù)據(jù)累計達(dá)到某些設(shè)定的伐值的時候,就會觸發(fā)一次DUMP操作倦青,將變化的數(shù)據(jù)一次性寫入數(shù)據(jù)文件(RDB文件)
(2)AOF 工作原理: 是將數(shù)據(jù)也是先存在內(nèi)存瓮床,但是固定時候會使用調(diào)用fsync來完成對本次寫操作的日志記錄,這個日志揭露文件其實是一個基于Redis網(wǎng)絡(luò)交互協(xié)議的文本文件产镐。AOF調(diào)用fsync也不是說全部都是無阻塞的隘庄,在某些系統(tǒng)上可能出現(xiàn)fsync阻塞進(jìn)程的情況,對于這種情況可以通過配置修改癣亚,但默認(rèn)情況不要修改丑掺。AOF最關(guān)鍵的配置就是關(guān)于調(diào)用fsync追加日志文件的頻率,有兩種預(yù)設(shè)頻率述雾,always每次記錄進(jìn)來都添加街州,everysecond 每秒添加一次。當(dāng)redis重啟時玻孟,將會讀取AOF文件進(jìn)行“重放”以恢復(fù)到redis關(guān)閉前的最后時刻菇肃。
(3)兩種存儲原理比較:
a.性能 Snapshot方式的性能是要明顯高于AOF方式的,原因有兩點: 采用2進(jìn)制方式存儲數(shù)據(jù)取募,數(shù)據(jù)文件比較小,加載快速蟆技。存儲的時候是按照配置中的save策略來存儲玩敏,每次都是聚合很多數(shù)據(jù)批量存儲,寫入的效率很好质礼,而AOF則一般都是工作在實時存儲或者準(zhǔn)實時模式下旺聚。相對來說存儲的頻率高,效率卻偏低眶蕉。 b.數(shù)據(jù)安全 AOF數(shù)據(jù)安全性高于Snapshot存儲砰粹,原因: Snapshot存儲是基于累計批量的思想,也就是說在允許的情況下造挽,累計的數(shù)據(jù)越多那么寫入效率也就越高碱璃,但數(shù)據(jù)的累計是靠時間的積累完成的弄痹,那么如果在長時間數(shù)據(jù)不寫入RDB,但Redis又遇到了崩潰嵌器,那么沒有寫入的數(shù)據(jù)就無法恢復(fù)了肛真,但是AOF方式偏偏相反,根據(jù)AOF配置的存儲頻率的策略可以做到最少的數(shù)據(jù)丟失和較高的數(shù)據(jù)恢復(fù)能力爽航。
-
Memcached
1蚓让、Memcached不支持內(nèi)存數(shù)據(jù)的持久化操作,所以的數(shù)據(jù)都以in-momory的形成存儲讥珍。
數(shù)據(jù)類型:
-
Mongo
1历极、字符串、整型衷佃、布爾型趟卸、雙進(jìn)度浮點型...具體參照:http://www.yiibai.com/mongodb/mongodb_datatype.html
-
Redis
1、除了簡單的key-value數(shù)據(jù)類型纲酗,同時還提供了list衰腌、hash、set觅赊、zset等數(shù)據(jù)結(jié)構(gòu)的存儲
-
Memcached
1右蕊、Memcached使用key-value形式存儲和訪問數(shù)據(jù)
網(wǎng)絡(luò)IO模型
-
Mongo
1、多線程吮螺,同步 IO 模型饶囚。
image.png
由主線程進(jìn)行 accept 連接,然后針對每一個連接創(chuàng)建一個線程進(jìn)行處理鸠补,「thread per connection」這種模型:
(1)不適合短連接服務(wù)萝风,創(chuàng)建/刪除線程的開銷是巨大的,體現(xiàn)在創(chuàng)建線程時間和至少1MB 內(nèi)存的使用紫岩。
(2)伸縮性受到線程數(shù)的限制规惰,200+線程數(shù)的調(diào)度對 OS 也是不小的負(fù)擔(dān)。另外隨著線程數(shù)的增加, 由于 mongo 本身業(yè)務(wù)的特性泉蝌,對數(shù)據(jù)處理的并發(fā)度并不高歇万,DB鎖和全局的原子操作造成的 context-switch 也是急劇上升,性能反而下降勋陪,頻繁的線程切換對于 cache 也不友好贪磺。
-
Redis
1、Redis使用 單線程的IO復(fù)用模型 诅愚,自己封裝了一個簡單的Ae_Event事件處理框架寒锚,主要實現(xiàn)了epoll、kqueue、kvport和select刹前,對于單存只有IO操作來說泳赋,單線程可以將速度優(yōu)勢發(fā)揮到最大,但是Redis也提供了一些簡單的計算功能腮郊,比如排序摹蘑、聚合等,對于這些操作轧飞,單線程模型不能發(fā)揮多核CPU的優(yōu)勢衅鹿,會嚴(yán)重影響整體吞吐率,因為在CPU的計算的過程中过咬,整個IO調(diào)度是被阻塞的大渤,因此 Redis不適合用于計算。
-
Memcached
1掸绞、Memcached是 多線程泵三、非阻塞IO復(fù)用 的網(wǎng)絡(luò)模型,分為監(jiān)聽主線程和worker子線程衔掸,監(jiān)聽線程監(jiān)聽網(wǎng)絡(luò)連接烫幕,接受請求后,將連接描述字pipe傳遞給worker線程進(jìn)行讀寫IO敞映,網(wǎng)絡(luò)層使用libevent封裝的事件庫较曼,多線程模型可以發(fā)揮CPU多核作用,但是引入了cache coherency(緩存一致性)和鎖的問題振愿,比如:Memcached最常用的stats命令捷犹,實際Memcached所有操作都要對這個全局變量加鎖、進(jìn)行技術(shù)工作等冕末,帶來了性能損耗萍歉。(緩存的一致性就是指緩存中的數(shù)據(jù)是否和目標(biāo)存儲中的數(shù)據(jù)是一樣的,也就是說緩存中已經(jīng)修改得數(shù)據(jù)是否已經(jīng)保存到了物理存儲中档桃,物理存儲中已經(jīng)被修改得內(nèi)容枪孩,是否與緩存的內(nèi)容是一樣的。這就是一致性的概念藻肄。)
內(nèi)存管理機(jī)制
-
Redis
1销凑、Redis的內(nèi)存管理主要通過源碼中的zmalloc.h和zmalloc.c兩個文件來實現(xiàn)。Redis為了方便內(nèi)存的管理仅炊,在分配了一塊內(nèi)存后,會將這塊內(nèi)存的大小存入內(nèi)存塊的頭部澎蛛。如下圖所示抚垄,real_ptr是Redis調(diào)用malloc函數(shù)返回的指針,Redis將內(nèi)存塊的大小size存入頭部(size所占據(jù)的大小是已知的,為size_t類型的長度)呆馁,然后返回ret_ptr桐经。當(dāng)需要釋放內(nèi)存的時候,ret_ptr別傳給內(nèi)存管理程序浙滤,通過ret_ptr可以很容易計算出real_ptr的值阴挣,然后將real_ptr傳給free釋放掉。
image.png
2纺腊、在Redis中畔咧,并不是所有的數(shù)組都一直存儲在內(nèi)存中的。這是和Memcached相比最大的一個區(qū)別揖膜。當(dāng)物理內(nèi)存用完的時候誓沸,Redis可以將一些很久沒用到的value交換到磁盤(注:這里用到的是Redis的Virtual Memory技術(shù),Redis2.4版本之后已經(jīng)不提倡使用了)壹粟。Redis只會緩存所有key的信息拜隧,如果Redis發(fā)現(xiàn)內(nèi)存的使用量超過了某個閾值,將觸發(fā)swap操作趁仙。swap操作根據(jù)規(guī)則計算出哪些key對應(yīng)的value需要swap到磁盤洪添,然后再將這些key對應(yīng)的value持久化到磁盤中,同時在內(nèi)存中清除雀费。這種特性使得Redis可以保存超過其機(jī)器物理內(nèi)存大小的數(shù)據(jù)干奢。當(dāng)然,機(jī)器本身的內(nèi)存必須要能夠保存所有的key坐儿,畢竟這部分?jǐn)?shù)據(jù)是不會被swap到磁盤的律胀。同時由于Redis將內(nèi)存中的數(shù)據(jù)swap到磁盤的時候,提供服務(wù)的主線程和進(jìn)行swap的子線程會共享這部分內(nèi)存貌矿,所有如果需要更新swap的數(shù)據(jù)炭菌,Redis將阻塞這個操作,直到子線程完成swap之后才可以進(jìn)行修改逛漫。當(dāng)從Redis中讀取數(shù)據(jù)的時候黑低,如果讀取的key的value不在內(nèi)存中,那么Redis需要從swap文件中加載對應(yīng)的數(shù)據(jù)酌毡,然后再返回給client克握,這里就存在一個I/O線程池的問題。在默認(rèn)情況下枷踏,Redis會出現(xiàn)阻塞菩暗,即完成所有的swap文件加載后才會執(zhí)行相應(yīng)的操作。這種策略在client數(shù)量較小旭蠕,進(jìn)行批量操作的時候比較合適停团。但是如果Redis應(yīng)用在一個大型的網(wǎng)站應(yīng)用中旷坦,這顯示是無法滿足大并發(fā)的情況的。所以Redis允許我們設(shè)置I/O線程池的大小佑稠,對需要從swap文件中加載相應(yīng)數(shù)據(jù)的讀取請求進(jìn)行并發(fā)操作秒梅,減少阻塞的時間。
-
Memcached
1舌胶、Memcached默認(rèn)使用Slab Allocation機(jī)制來管理內(nèi)存捆蜀,它的主要思想是 按照預(yù)先規(guī)定的大小,將分配的內(nèi)存分割成特定長度的塊幔嫂,以存儲相應(yīng)長度的key-value數(shù)據(jù)記錄辆它,以完全解決內(nèi)存碎片的問題。Slab Allocation機(jī)制只為存儲外部數(shù)據(jù)而設(shè)計婉烟,也就是說所有的key-value數(shù)據(jù)都存儲在slab allocation系統(tǒng)里面娩井,但是Memcached的其他內(nèi)存請求則是通過普通的malloc/free來申請,因為這些請求的數(shù)量和頻率決定了它們不會對整個系統(tǒng)的性能造成影響似袁。
2洞辣、slab allocation機(jī)制的原理比較簡單,如下圖所示昙衅,它首先從操作系統(tǒng)申請一大塊內(nèi)存扬霜,并將其分割成各種尺寸的chunk(塊),并把尺寸相同的chunk分成一組組slab class而涉。其中著瓶,chunk就是用來存儲key-value的最小單位。每個slab class的大小啼县,可以在Memcached啟動的時候通過制定growth factor來控制材原。
image.png
3、當(dāng)Memcached接收到客戶端發(fā)過來的數(shù)據(jù)時季眷,會根據(jù)收到數(shù)據(jù)的大小選擇一個最合適的slab class余蟹,然后通過查詢Memcached保存著的該slab class內(nèi)空閑chunk的列表,就可以找到一個用于存儲數(shù)據(jù)的chunk子刮。當(dāng)一條數(shù)據(jù)記錄過期或者丟棄時威酒,該記錄所占用的chunk就可以被回收,重新添加到空閑列表中挺峡。
4葵孤、從以上過程中可以看到,Memcached的內(nèi)存管理效率高橱赠,并且不會造成內(nèi)存碎片尤仍,但是它最大的不足是會造成空間浪費(fèi)。因為每個chunk都分配了特定長度的內(nèi)存空間狭姨,所以變長數(shù)據(jù)無法利用這些空間吓著。如下圖所示鲤嫡,將100字節(jié)的數(shù)據(jù)緩存到128字節(jié)的chunk中,剩余的28個字節(jié)就被浪費(fèi)掉了绑莺。
集群管理
-
Mongo
1、Replica Set:中文翻譯叫做副本集惕耕,就是集群當(dāng)中包含了多份數(shù)據(jù)纺裁,保證主節(jié)點掛掉了,備節(jié)點能繼續(xù)提供數(shù)據(jù)服務(wù)司澎,提供的前提就是數(shù)據(jù)需要和主節(jié)點一致欺缘。如下圖:
2、Mongodb(M)表示主節(jié)點挤安,Mongodb(S)表示備節(jié)點谚殊,Mongodb(A)表示仲裁節(jié)點。主備節(jié)點存儲數(shù)據(jù)蛤铜,仲裁節(jié)點不存儲數(shù)據(jù)嫩絮。客戶端同時連接主節(jié)點與備節(jié)點围肥,不連接仲裁節(jié)點剿干。
3蜡坊、默認(rèn)設(shè)置下叔锐,主節(jié)點提供所有增刪查改服務(wù)欢摄,備節(jié)點不提供任何服務(wù)依鸥。但是可以通過設(shè)置使備節(jié)點提供查詢服務(wù)曼追,這樣就可以減少主節(jié)點的壓力粉铐,當(dāng)客戶端進(jìn)行數(shù)據(jù)查詢時亥贸,請求自動轉(zhuǎn)到備節(jié)點上导饲。這個設(shè)置叫做Read Preference Modes朵锣,同時Java客戶端提供了簡單的配置方式谬盐,可以不必直接對數(shù)據(jù)庫進(jìn)行操作。
4猪勇、仲裁節(jié)點是一種特殊的節(jié)點设褐,它本身并不存儲數(shù)據(jù),主要的作用是決定哪一個備節(jié)點在主節(jié)點掛掉之后提升為主節(jié)點泣刹,所以客戶端不需要連接此節(jié)點助析。這里雖然只有一個備節(jié)點,但是仍然需要一個仲裁節(jié)點來提升備節(jié)點級別(由備用節(jié)點提升為主節(jié)點)椅您。仲裁節(jié)點是必須的外冀。詳見:http://blog.csdn.net/luonanqin/article/details/8497860
-
Redis
1、相比Memcached只能采用客戶端實現(xiàn)分布式存儲掀泳,Redis更偏向在服務(wù)端構(gòu)建分布式存儲雪隧。新版本的Redis已經(jīng)支持分布式存儲功能西轩。Redis Cluster是一個實現(xiàn)了分布式并且允許單點故障的Redis高級版本,它沒有中心節(jié)點脑沿,具有線性可伸縮的功能藕畔。Redis Cluster的分布式存儲架構(gòu),節(jié)點與節(jié)點之間通過二進(jìn)制協(xié)議進(jìn)行通訊庄拇,節(jié)點與客戶端之間通過ascii協(xié)議通訊注服。在數(shù)據(jù)的放置策略上,Redis Cluster將整個key的數(shù)值域劃分成16384(2^14)個哈希槽措近,每個節(jié)點上可以存儲一個或多個哈希槽溶弟,也就是說Redis Cluster支持的最大節(jié)點數(shù)是16384。
2瞭郑、為了保證單點故障下得數(shù)據(jù)可用性辜御,Redis Cluster引入了Master節(jié)點和Slave節(jié)點。在Redis Cluster中屈张,每個Master節(jié)點都會對應(yīng)2個用于冗余的Slave節(jié)點擒权。這樣在整個集群中,任意2個節(jié)點的宕機(jī)都不會導(dǎo)致數(shù)據(jù)的不可用袜茧。當(dāng)Master節(jié)點下線后菜拓,集群會自動選擇一個Slave節(jié)點成為新的Master節(jié)點。
-
Memcached
1笛厦、Memcached是全內(nèi)存的數(shù)據(jù)緩沖系統(tǒng)纳鼎,Redis雖然支持?jǐn)?shù)據(jù)的持久化,但是全內(nèi)存才是其高性能的本質(zhì)裳凸。作為基于內(nèi)存的存儲系統(tǒng)來說贱鄙,機(jī)器物理內(nèi)存的大小就是系統(tǒng)能夠容納的最大數(shù)據(jù)量。如果數(shù)據(jù)超過了單臺機(jī)器的物理內(nèi)存大小姨谷,那么就需要構(gòu)建集群來擴(kuò)展存儲能力逗宁。
2、Memcached本身并不支持分布式梦湘,因此只能在客戶端通過像一致性哈希這樣的分布式算法來實現(xiàn)Memcached的分布式存儲瞎颗。
應(yīng)用場景
-
Memcached及Redis
1、相對memcached來說捌议,需要保證數(shù)據(jù)不丟失的話哼拔,選擇Redis。
2瓣颅、當(dāng)然倦逐,大部分情況來說,選擇Redis是一個更好的選擇宫补,因為它更強(qiáng)大檬姥、更受歡迎曾我,并且比Memcached有更多的支持者。Memcached只是Redis功能中的一小部分健民。所以對于新項目來說抒巢,選擇Redis。
-
Mongo
1秉犹、Mongo的使用和上面兩個數(shù)據(jù)庫是不沖突的虐秦,這篇文字只是做一個知識的總結(jié)。
2凤优、日志、消息記錄蜈彼;不需要事務(wù)筑辨,不需復(fù)雜join連接表;需要大容量存儲幸逆;高吞吐量棍辕;數(shù)據(jù)不丟失;高可用还绘;使用Mongo楚昭。
參考:
http://blog.csdn.net/sun491922556/article/details/76423178?locationNum=1&fps=1