分布式緩存Redis之與Memcached的比較

寫在前面
??本學(xué)習(xí)教程所有示例代碼見GitHub:https://github.com/selfconzrr/Redis_Learning

由于在項(xiàng)目中并沒有使用Memcached鸟妙,所以在這貼出Memcached的教程,以備不時(shí)之需陈惰。

http://www.runoob.com/Memcached/Memcached-tutorial.html

Redis的作者Salvatore Sanfilippo曾經(jīng)對(duì)這兩種基于內(nèi)存的數(shù)據(jù)存儲(chǔ)系統(tǒng)進(jìn)行過比較山涡,總體來看還是比較客觀的幻碱。

一狂秦、性能
??由于Redis只使用單核蚯涮,而Memcached可以使用多核治专,所以平均每一個(gè)核上Redis在存儲(chǔ)小數(shù)據(jù)時(shí)比Memcached性能更高。而在100k以上的數(shù)據(jù)時(shí)遭顶,Memcached性能要高于Redis张峰,雖然Redis最近也在存儲(chǔ)大數(shù)據(jù)的性能上進(jìn)行優(yōu)化,但是比起Memcached棒旗,還是稍有遜色喘批。

二、內(nèi)存使用效率
??使用簡(jiǎn)單的key-value存儲(chǔ)的話铣揉,Memcached的內(nèi)存利用率更高饶深,而如果Redis采用hash結(jié)構(gòu)來做key-value存儲(chǔ),由于其組合式的壓縮逛拱,其內(nèi)存利用率會(huì)高于Memcached敌厘。

三、Redis支持服務(wù)器端的數(shù)據(jù)操作
??Redis相比Memcached來說朽合,擁有更多的數(shù)據(jù)結(jié)構(gòu)并支持更豐富的數(shù)據(jù)操作俱两,通常在Memcached里,你需要將數(shù)據(jù)拿到客戶端來進(jìn)行類似的修改再set回去曹步,序列化再反序列化宪彩,這大大增加了網(wǎng)絡(luò)IO的次數(shù)和數(shù)據(jù)體積。在Redis中讲婚,這些復(fù)雜的操作通常和一般的GET/SET一樣高效毯焕。所以,如果需要緩存能夠支持更復(fù)雜的結(jié)構(gòu)和操作,那么Redis會(huì)是不錯(cuò)的選擇纳猫。

與Memcached僅支持簡(jiǎn)單的key-value結(jié)構(gòu)的數(shù)據(jù)記錄不同婆咸,Redis支持的數(shù)據(jù)類型要豐富得多。最為常用的數(shù)據(jù)類型主要由五種:String芜辕、Hash尚骄、List、Set和Sorted Set侵续。Redis內(nèi)部使用一個(gè)redisObject對(duì)象來表示所有的key和value倔丈。

四、數(shù)據(jù)備份恢復(fù)
??memcached掛掉后状蜗,數(shù)據(jù)不可恢復(fù)需五;redis數(shù)據(jù)丟失后可以通過aof恢復(fù),Redis支持?jǐn)?shù)據(jù)的備份轧坎,即master-slave主從模式的數(shù)據(jù)備份宏邮。

五、數(shù)據(jù)存儲(chǔ)
??Redis和Memcached都是將數(shù)據(jù)存放在內(nèi)存中缸血,都是內(nèi)存數(shù)據(jù)庫(kù)蜜氨。不過memcached還可用于緩存其他東西,例如圖片捎泻、視頻等等飒炎。memcached把數(shù)據(jù)全部存在內(nèi)存之中,斷電后會(huì)掛掉笆豁,數(shù)據(jù)不能超過內(nèi)存大欣赏簟;redis有部份存在硬盤上闯狱,這樣能保證數(shù)據(jù)的持久性煞赢,支持?jǐn)?shù)據(jù)的持久化(RDB、AOF)扩氢,而Memcached不支持持久化窒典。同時(shí)Redis并不是所有的數(shù)據(jù)都一直存儲(chǔ)在內(nèi)存中的旱物,當(dāng)物理內(nèi)存用完時(shí)猾浦,Redis可以將一些很久沒用到的value交換到磁盤钓株,但memcached超過內(nèi)存比例會(huì)抹掉前面的數(shù)據(jù)侥衬。

六橱野、內(nèi)存管理機(jī)制
??對(duì)于像Redis和Memcached這種基于內(nèi)存的數(shù)據(jù)庫(kù)系統(tǒng)來說叫潦,內(nèi)存管理的效率高低是影響系統(tǒng)性能的關(guān)鍵因素五续。傳統(tǒng)C語言中的malloc/free函數(shù)是最常用的分配和釋放內(nèi)存的方法弟断,但是這種方法存在著很大的缺陷:首先咏花,對(duì)于開發(fā)人員來說不匹配的malloc和free容易造成內(nèi)存泄露;其次頻繁調(diào)用會(huì)造成大量?jī)?nèi)存碎片無法回收重新利用,降低內(nèi)存利用率昏翰;最后作為系統(tǒng)調(diào)用苍匆,其系統(tǒng)開銷遠(yuǎn)遠(yuǎn)大于一般函數(shù)調(diào)用。所以棚菊,為了提高內(nèi)存的管理效率浸踩,高效的內(nèi)存管理方案都不會(huì)直接使用malloc/free調(diào)用。

Memcached默認(rèn)使用Slab Allocation機(jī)制管理內(nèi)存统求,其主要思想是按照預(yù)先規(guī)定的大小检碗,將分配的內(nèi)存分割成特定長(zhǎng)度的塊以存儲(chǔ)相應(yīng)長(zhǎng)度的key-value數(shù)據(jù)記錄,以完全解決內(nèi)存碎片問題码邻。Slab Allocation機(jī)制只為存儲(chǔ)外部數(shù)據(jù)而設(shè)計(jì)折剃,也就是說所有的key-value數(shù)據(jù)都存儲(chǔ)在Slab Allocation系統(tǒng)里,而Memcached的其它內(nèi)存請(qǐng)求則通過普通的malloc/free來申請(qǐng)像屋,因?yàn)檫@些請(qǐng)求的數(shù)量和頻率決定了它們不會(huì)對(duì)整個(gè)系統(tǒng)的性能造成影響怕犁。

如圖所示,它首先從操作系統(tǒng)申請(qǐng)一大塊內(nèi)存开睡,并將其分割成各種尺寸的塊Chunk因苹,并把尺寸相同的塊分成組Slab Class。其中篇恒,Chunk就是用來存儲(chǔ)key-value數(shù)據(jù)的最小單位扶檐。每個(gè)Slab Class的大小,可以在Memcached啟動(dòng)的時(shí)候通過制定Growth Factor來控制胁艰。假定圖中Growth Factor的取值為1.25款筑,如果第一組Chunk的大小為88個(gè)字節(jié),第二組Chunk的大小就為112個(gè)字節(jié)腾么,依此類推奈梳。

當(dāng)Memcached接收到客戶端發(fā)送過來的數(shù)據(jù)時(shí)首先會(huì)根據(jù)收到數(shù)據(jù)的大小選擇一個(gè)最合適的Slab Class,然后通過查詢Memcached保存著的該Slab Class內(nèi)空閑Chunk的列表就可以找到一個(gè)可用于存儲(chǔ)數(shù)據(jù)的Chunk解虱。當(dāng)一條數(shù)據(jù)庫(kù)過期或者丟棄時(shí)攘须,該記錄所占用的Chunk就可以回收,重新添加到空閑列表中殴泰。

從以上過程我們可以看出Memcached的內(nèi)存管理制效率高于宙,而且不會(huì)造成內(nèi)存碎片,但是它最大的缺點(diǎn)就是會(huì)導(dǎo)致空間浪費(fèi)悍汛。因?yàn)槊總€(gè)Chunk都分配了特定長(zhǎng)度的內(nèi)存空間捞魁,所以變長(zhǎng)數(shù)據(jù)無法充分利用這些空間。比如將100個(gè)字節(jié)的數(shù)據(jù)緩存到128個(gè)字節(jié)的Chunk中离咐,剩余的28個(gè)字節(jié)就浪費(fèi)掉了谱俭。Memcached主要的cache機(jī)制是LRU(最近最少使用Least Recently Used)算法+超時(shí)失效。

Redis的內(nèi)存管理主要通過源碼中zmalloc.h和zmalloc.c兩個(gè)文件來實(shí)現(xiàn)的。Redis為了方便內(nèi)存的管理昆著,在分配一塊內(nèi)存之后县貌,會(huì)將這塊內(nèi)存的大小存入內(nèi)存塊的頭部。

如圖所示宣吱,real_ptr是redis調(diào)用malloc后返回的指針窃这。redis將內(nèi)存塊的大小size存入頭部,size所占據(jù)的內(nèi)存大小是已知的征候,為size_t類型的長(zhǎng)度杭攻,然后返回ret_ptr。當(dāng)需要釋放內(nèi)存的時(shí)候疤坝,ret_ptr被傳給內(nèi)存管理程序兆解。通過ret_ptr,程序可以很容易的算出real_ptr的值跑揉,然后將real_ptr傳給free釋放內(nèi)存锅睛。

Redis通過定義一個(gè)數(shù)組來記錄所有的內(nèi)存分配情況,這個(gè)數(shù)組的長(zhǎng)度為ZMALLOC_MAX_ALLOC_STAT历谍。數(shù)組的每一個(gè)元素代表當(dāng)前程序所分配的內(nèi)存塊的個(gè)數(shù)现拒,且內(nèi)存塊的大小為該元素的下標(biāo)。在源碼中望侈,這個(gè)數(shù)組為zmalloc_allocations印蔬。zmalloc_allocations[16]代表已經(jīng)分配的長(zhǎng)度為16bytes的內(nèi)存塊的個(gè)數(shù)。zmalloc.c中有一個(gè)靜態(tài)變量used_memory用來記錄當(dāng)前分配的內(nèi)存總大小脱衙。所以侥猬,總的來看,Redis采用的是包裝的mallc/free捐韩,相較于Memcached的內(nèi)存管理方法來說退唠,要簡(jiǎn)單很多。

七荤胁、集群瞧预、分布式存儲(chǔ)
??Memcached是全內(nèi)存的數(shù)據(jù)緩沖系統(tǒng),Redis雖然支持?jǐn)?shù)據(jù)的持久化仅政,但是全內(nèi)存畢竟才是其高性能的本質(zhì)垢油。作為基于內(nèi)存的存儲(chǔ)系統(tǒng)來說,機(jī)器物理內(nèi)存的大小就是系統(tǒng)能夠容納的最大數(shù)據(jù)量已旧。如果需要處理的數(shù)據(jù)量超過了單臺(tái)機(jī)器的物理內(nèi)存大小秸苗,就需要構(gòu)建分布式集群來擴(kuò)展存儲(chǔ)能力召娜。

Memcached本身并不支持分布式运褪,因此只能在客戶端通過像一致性哈希這樣的分布式算法來實(shí)現(xiàn)Memcached的分布式存儲(chǔ),關(guān)于分布式一致性哈希算法見總結(jié):分布式一致性hash算法。當(dāng)客戶端向Memcached集群發(fā)送數(shù)據(jù)之前秸讹,首先會(huì)通過內(nèi)置的分布式算法計(jì)算出該條數(shù)據(jù)的目標(biāo)節(jié)點(diǎn)檀咙,然后數(shù)據(jù)會(huì)直接發(fā)送到該節(jié)點(diǎn)上存儲(chǔ)。但客戶端查詢數(shù)據(jù)時(shí)璃诀,同樣要計(jì)算出查詢數(shù)據(jù)所在的節(jié)點(diǎn)弧可,然后直接向該節(jié)點(diǎn)發(fā)送查詢請(qǐng)求以獲取數(shù)據(jù)。

相較于Memcached只能采用客戶端實(shí)現(xiàn)分布式存儲(chǔ)劣欢,Redis更偏向于在服務(wù)器端構(gòu)建分布式存儲(chǔ)棕诵,但沒有采用一致性哈希,關(guān)于Redis集群分析見總結(jié):分布式緩存Redis之cluster集群凿将。最新版本的Redis已經(jīng)支持了分布式存儲(chǔ)功能校套。Redis Cluster是一個(gè)實(shí)現(xiàn)了分布式且允許單點(diǎn)故障的Redis高級(jí)版本,它沒有中心節(jié)點(diǎn)牧抵,具有線性可伸縮的功能笛匙。為了保證單點(diǎn)故障下的數(shù)據(jù)可用性,Redis Cluster引入了Master節(jié)點(diǎn)和Slave節(jié)點(diǎn)犀变。在Redis Cluster中妹孙,每個(gè)Master節(jié)點(diǎn)都會(huì)有對(duì)應(yīng)的兩個(gè)用于冗余的Slave節(jié)點(diǎn)。這樣在整個(gè)集群中获枝,任意兩個(gè)節(jié)點(diǎn)的宕機(jī)都不會(huì)導(dǎo)致數(shù)據(jù)的不可用蠢正。當(dāng)Master節(jié)點(diǎn)退出后,集群會(huì)自動(dòng)選擇一個(gè)Slave節(jié)點(diǎn)成為新的Master節(jié)點(diǎn)映琳。

八机隙、Memcache支持多核多線程,Redis單線程操作

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末萨西,一起剝皮案震驚了整個(gè)濱河市有鹿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌谎脯,老刑警劉巖葱跋,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異源梭,居然都是意外死亡娱俺,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門废麻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來荠卷,“玉大人,你說我怎么就攤上這事烛愧∮鸵耍” “怎么了掂碱?”我有些...
    開封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)慎冤。 經(jīng)常有香客問我疼燥,道長(zhǎng),這世上最難降的妖魔是什么蚁堤? 我笑而不...
    開封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任醉者,我火速辦了婚禮,結(jié)果婚禮上披诗,老公的妹妹穿的比我還像新娘撬即。我一直安慰自己,他們只是感情好呈队,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開白布搞莺。 她就那樣靜靜地躺著,像睡著了一般掂咒。 火紅的嫁衣襯著肌膚如雪才沧。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天绍刮,我揣著相機(jī)與錄音温圆,去河邊找鬼。 笑死孩革,一個(gè)胖子當(dāng)著我的面吹牛岁歉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播膝蜈,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼锅移,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了饱搏?” 一聲冷哼從身側(cè)響起非剃,我...
    開封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎推沸,沒想到半個(gè)月后备绽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鬓催,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年肺素,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片宇驾。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡倍靡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出课舍,到底是詐尸還是另有隱情塌西,我是刑警寧澤蜗顽,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布,位于F島的核電站雨让,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏忿等。R本人自食惡果不足惜栖忠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望贸街。 院中可真熱鬧庵寞,春花似錦、人聲如沸薛匪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽逸尖。三九已至古沥,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間娇跟,已是汗流浹背岩齿。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留苞俘,地道東北人盹沈。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像吃谣,于是被迫代替她去往敵國(guó)和親乞封。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容