一致性hash史侣,MemCache詳細(xì)解讀

一致性Hash算法

從上面的圖中,可以看出一個(gè)很重要的問(wèn)題魏身,就是對(duì)服務(wù)器集群的管理惊橱,路由算法至關(guān)重要,就和負(fù)載均衡算法一樣箭昵,路由算法決定著究竟該訪問(wèn)集群中的哪臺(tái)服務(wù)器税朴,先看一個(gè)簡(jiǎn)單的路由算法。

1家制、余數(shù)Hash

比方說(shuō)正林,字符串str對(duì)應(yīng)的HashCode是50、服務(wù)器的數(shù)目是3颤殴,取余數(shù)得到2觅廓,str對(duì)應(yīng)節(jié)點(diǎn)Node2,所以路由算法把str路由到Node2服務(wù)器上涵但。由于HashCode隨機(jī)性比較強(qiáng)杈绸,所以使用余數(shù)Hash路由算法就可以保證緩存數(shù)據(jù)在整個(gè)MemCache服務(wù)器集群中有比較均衡的分布。

如果不考慮服務(wù)器集群的伸縮性(什么是伸縮性矮瘟,請(qǐng)參見(jiàn)大型網(wǎng)站架構(gòu)學(xué)習(xí)筆記)瞳脓,那么余數(shù)Hash算法幾乎可以滿足絕大多數(shù)的緩存路由需求,但是當(dāng)分布式緩存集群需要擴(kuò)容的時(shí)候澈侠,就難辦了劫侧。

就假設(shè)MemCache服務(wù)器集群由3臺(tái)變?yōu)?臺(tái)吧,更改服務(wù)器列表哨啃,仍然使用余數(shù)Hash烧栋,50對(duì)4的余數(shù)是2,對(duì)應(yīng)Node2棘催,但是str原來(lái)是存在Node1上的劲弦,這就導(dǎo)致了緩存沒(méi)有命中耳标。如果這么說(shuō)不夠明白醇坝,那么不妨舉個(gè)例子,原來(lái)有HashCode為0~19的20個(gè)數(shù)據(jù),那么:

HashCode012345678910111213141516171819

路由到的服務(wù)器01201201201201201201

現(xiàn)在我擴(kuò)容到4臺(tái)呼猪,加粗標(biāo)紅的表示命中:

HashCode012345678910111213141516171819

路由到的服務(wù)器01230123012301230123

如果我擴(kuò)容到20+的臺(tái)數(shù)画畅,只有前三個(gè)HashCode對(duì)應(yīng)的Key是命中的,也就是15%宋距。當(dāng)然這只是個(gè)簡(jiǎn)單例子轴踱,現(xiàn)實(shí)情況肯定比這個(gè)復(fù)雜得多,不過(guò)足以說(shuō)明谚赎,使用余數(shù)Hash的路由算法淫僻,在擴(kuò)容的時(shí)候會(huì)造成大量的數(shù)據(jù)無(wú)法正確命中(其實(shí)不僅僅是無(wú)法命中,那些大量的無(wú)法命中的數(shù)據(jù)還在原緩存中在被移除前占據(jù)著內(nèi)存)壶唤。這個(gè)結(jié)果顯然是無(wú)法接受的雳灵,在網(wǎng)站業(yè)務(wù)中,大部分的業(yè)務(wù)數(shù)據(jù)度操作請(qǐng)求上事實(shí)上是通過(guò)緩存獲取的闸盔,只有少量讀操作會(huì)訪問(wèn)數(shù)據(jù)庫(kù)悯辙,因此數(shù)據(jù)庫(kù)的負(fù)載能力是以有緩存為前提而設(shè)計(jì)的。當(dāng)大部分被緩存了的數(shù)據(jù)因?yàn)榉?wù)器擴(kuò)容而不能正確讀取時(shí)迎吵,這些數(shù)據(jù)訪問(wèn)的壓力就落在了數(shù)據(jù)庫(kù)的身上躲撰,這將大大超過(guò)數(shù)據(jù)庫(kù)的負(fù)載能力,嚴(yán)重的可能會(huì)導(dǎo)致數(shù)據(jù)庫(kù)宕機(jī)击费。

這個(gè)問(wèn)題有解決方案拢蛋,解決步驟為:

(1)在網(wǎng)站訪問(wèn)量低谷,通常是深夜蔫巩,技術(shù)團(tuán)隊(duì)加班瓤狐,擴(kuò)容、重啟服務(wù)器

(2)通過(guò)模擬請(qǐng)求的方式逐漸預(yù)熱緩存批幌,使緩存服務(wù)器中的數(shù)據(jù)重新分布

2础锐、一致性Hash算法

一致性Hash算法通過(guò)一個(gè)叫做一致性Hash環(huán)的數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)Key到緩存服務(wù)器的Hash映射,看一下我自己畫(huà)的一張圖:

具體算法過(guò)程為:先構(gòu)造一個(gè)長(zhǎng)度為232的整數(shù)環(huán)(這個(gè)環(huán)被稱(chēng)為一致性Hash環(huán))荧缘,根據(jù)節(jié)點(diǎn)名稱(chēng)的Hash值(其分布為[0, 232-1])將緩存服務(wù)器節(jié)點(diǎn)放置在這個(gè)Hash環(huán)上皆警,然后根據(jù)需要緩存的數(shù)據(jù)的Key值計(jì)算得到其Hash值(其分布也為[0, 232-1]),然后在Hash環(huán)上順時(shí)針查找距離這個(gè)Key值的Hash值最近的服務(wù)器節(jié)點(diǎn)截粗,完成Key到服務(wù)器的映射查找信姓。

就如同圖上所示,三個(gè)Node點(diǎn)分別位于Hash環(huán)上的三個(gè)位置绸罗,然后Key值根據(jù)其HashCode意推,在Hash環(huán)上有一個(gè)固定位置,位置固定下之后珊蟀,Key就會(huì)順時(shí)針去尋找離它最近的一個(gè)Node菊值,把數(shù)據(jù)存儲(chǔ)在這個(gè)Node的MemCache服務(wù)器中。使用Hash環(huán)如果加了一個(gè)節(jié)點(diǎn)會(huì)怎么樣,看一下:

看到我加了一個(gè)Node4節(jié)點(diǎn)腻窒,只影響到了一個(gè)Key值的數(shù)據(jù)昵宇,本來(lái)這個(gè)Key值應(yīng)該是在Node1服務(wù)器上的,現(xiàn)在要去Node4了儿子。采用一致性Hash算法瓦哎,的確也會(huì)影響到整個(gè)集群,但是影響的只是加粗的那一段而已柔逼,相比余數(shù)Hash算法影響了遠(yuǎn)超一半的影響率蒋譬,這種影響要小得多。更重要的是愉适,集群中緩存服務(wù)器節(jié)點(diǎn)越多羡铲,增加節(jié)點(diǎn)帶來(lái)的影響越小,很好理解儡毕。換句話說(shuō)也切,隨著集群規(guī)模的增大,繼續(xù)命中原有緩存數(shù)據(jù)的概率會(huì)越來(lái)越大腰湾,雖然仍然有小部分?jǐn)?shù)據(jù)緩存在服務(wù)器中不能被讀到雷恃,但是這個(gè)比例足夠小,即使訪問(wèn)數(shù)據(jù)庫(kù)费坊,也不會(huì)對(duì)數(shù)據(jù)庫(kù)造成致命的負(fù)載壓力倒槐。

至于具體應(yīng)用,這個(gè)長(zhǎng)度為232的一致性Hash環(huán)通常使用二叉查找樹(shù)實(shí)現(xiàn)附井,至于二叉查找樹(shù)讨越,就是算法的問(wèn)題了,可以自己去查詢(xún)相關(guān)資料永毅。


MemCache是什么

MemCache是一個(gè)自由把跨、源碼開(kāi)放、高性能沼死、分布式的分布式內(nèi)存對(duì)象緩存系統(tǒng)着逐,用于動(dòng)態(tài)Web應(yīng)用以減輕數(shù)據(jù)庫(kù)的負(fù)載。它通過(guò)在內(nèi)存中緩存數(shù)據(jù)和對(duì)象來(lái)減少讀取數(shù)據(jù)庫(kù)的次數(shù)意蛀,從而提高了網(wǎng)站訪問(wèn)的速度耸别。MemCaChe是一個(gè)存儲(chǔ)鍵值對(duì)的HashMap,在內(nèi)存中對(duì)任意的數(shù)據(jù)(比如字符串县钥、對(duì)象等)所使用的key-value存儲(chǔ)秀姐,數(shù)據(jù)可以來(lái)自數(shù)據(jù)庫(kù)調(diào)用、API調(diào)用若贮,或者頁(yè)面渲染的結(jié)果省有。MemCache設(shè)計(jì)理念就是小而強(qiáng)大痒留,它簡(jiǎn)單的設(shè)計(jì)促進(jìn)了快速部署、易于開(kāi)發(fā)并解決面對(duì)大規(guī)模的數(shù)據(jù)緩存的許多難題锥咸,而所開(kāi)放的API使得MemCache能用于Java、C/C++/C#细移、Perl搏予、Python、PHP弧轧、Ruby等大部分流行的程序語(yǔ)言雪侥。

另外,說(shuō)一下MemCache和MemCached的區(qū)別:

1精绎、MemCache是項(xiàng)目的名稱(chēng)

2速缨、MemCached是MemCache服務(wù)器端可以執(zhí)行文件的名稱(chēng)

MemCache的官方網(wǎng)站為http://memcached.org/

MemCache訪問(wèn)模型

為了加深理解,我模仿著原阿里技術(shù)專(zhuān)家李智慧老師《大型網(wǎng)站技術(shù)架構(gòu) 核心原理與案例分析》一書(shū)MemCache部分代乃,自己畫(huà)了一張圖:

特別澄清一個(gè)問(wèn)題旬牲,MemCache雖然被稱(chēng)為"分布式緩存",但是MemCache本身完全不具備分布式的功能搁吓,MemCache集群之間不會(huì)相互通信(與之形成對(duì)比的原茅,比如JBoss Cache,某臺(tái)服務(wù)器有緩存數(shù)據(jù)更新時(shí)堕仔,會(huì)通知集群中其他機(jī)器更新緩存或清除緩存數(shù)據(jù))擂橘,所謂的"分布式",完全依賴(lài)于客戶端程序的實(shí)現(xiàn)摩骨,就像上面這張圖的流程一樣通贞。

同時(shí)基于這張圖,理一下MemCache一次寫(xiě)緩存的流程:

1恼五、應(yīng)用程序輸入需要寫(xiě)緩存的數(shù)據(jù)

2昌罩、API將Key輸入路由算法模塊,路由算法根據(jù)Key和MemCache集群服務(wù)器列表得到一臺(tái)服務(wù)器編號(hào)

3灾馒、由服務(wù)器編號(hào)得到MemCache及其的ip地址和端口號(hào)

4峡迷、API調(diào)用通信模塊和指定編號(hào)的服務(wù)器通信,將數(shù)據(jù)寫(xiě)入該服務(wù)器你虹,完成一次分布式緩存的寫(xiě)操作

讀緩存和寫(xiě)緩存一樣绘搞,只要使用相同的路由算法和服務(wù)器列表,只要應(yīng)用程序查詢(xún)的是相同的Key傅物,MemCache客戶端總是訪問(wèn)相同的客戶端去讀取數(shù)據(jù)夯辖,只要服務(wù)器中還緩存著該數(shù)據(jù),就能保證緩存命中董饰。

這種MemCache集群的方式也是從分區(qū)容錯(cuò)性的方面考慮的蒿褂,假如Node2宕機(jī)了圆米,那么Node2上面存儲(chǔ)的數(shù)據(jù)都不可用了,此時(shí)由于集群中Node0和Node1還存在啄栓,下一次請(qǐng)求Node2中存儲(chǔ)的Key值的時(shí)候娄帖,肯定是沒(méi)有命中的,這時(shí)先從數(shù)據(jù)庫(kù)中拿到要緩存的數(shù)據(jù)昙楚,然后路由算法模塊根據(jù)Key值在Node0和Node1中選取一個(gè)節(jié)點(diǎn)近速,把對(duì)應(yīng)的數(shù)據(jù)放進(jìn)去,這樣下一次就又可以走緩存了堪旧,這種集群的做法很好削葱,但是缺點(diǎn)是成本比較大。

MemCache實(shí)現(xiàn)原理

首先要說(shuō)明一點(diǎn)淳梦,MemCache的數(shù)據(jù)存放在內(nèi)存中析砸,存放在內(nèi)存中個(gè)人認(rèn)為意味著幾點(diǎn):

1、訪問(wèn)數(shù)據(jù)的速度比傳統(tǒng)的關(guān)系型數(shù)據(jù)庫(kù)要快爆袍,因?yàn)镺racle首繁、MySQL這些傳統(tǒng)的關(guān)系型數(shù)據(jù)庫(kù)為了保持?jǐn)?shù)據(jù)的持久性,數(shù)據(jù)存放在硬盤(pán)中陨囊,IO操作速度慢

2蛮瞄、MemCache的數(shù)據(jù)存放在內(nèi)存中同時(shí)意味著只要MemCache重啟了,數(shù)據(jù)就會(huì)消失

3谆扎、既然MemCache的數(shù)據(jù)存放在內(nèi)存中挂捅,那么勢(shì)必受到機(jī)器位數(shù)的限制,這個(gè)之前的文章寫(xiě)過(guò)很多次了堂湖,32位機(jī)器最多只能使用2GB的內(nèi)存空間闲先,64位機(jī)器可以認(rèn)為沒(méi)有上限

然后我們來(lái)看一下MemCache的原理,MemCache最重要的莫不是內(nèi)存分配的內(nèi)容了无蜂,MemCache采用的內(nèi)存分配方式是固定空間分配伺糠,還是自己畫(huà)一張圖說(shuō)明:

這張圖片里面涉及了slab_class、slab斥季、page训桶、chunk四個(gè)概念,它們之間的關(guān)系是:

1酣倾、MemCache將內(nèi)存空間分為一組slab

2舵揭、每個(gè)slab下又有若干個(gè)page,每個(gè)page默認(rèn)是1M躁锡,如果一個(gè)slab占用100M內(nèi)存的話午绳,那么這個(gè)slab下應(yīng)該有100個(gè)page

3、每個(gè)page里面包含一組chunk映之,chunk是真正存放數(shù)據(jù)的地方拦焚,同一個(gè)slab里面的chunk的大小是固定的

4蜡坊、有相同大小chunk的slab被組織在一起,稱(chēng)為slab_class

MemCache內(nèi)存分配的方式稱(chēng)為allocator赎败,slab的數(shù)量是有限的秕衙,幾個(gè)、十幾個(gè)或者幾十個(gè)僵刮,這個(gè)和啟動(dòng)參數(shù)的配置相關(guān)据忘。

MemCache中的value過(guò)來(lái)存放的地方是由value的大小決定的,value總是會(huì)被存放到與chunk大小最接近的一個(gè)slab中妓笙,比如slab[1]的chunk大小為80字節(jié)若河、slab[2]的chunk大小為100字節(jié)能岩、slab[3]的chunk大小為128字節(jié)(相鄰slab內(nèi)的chunk基本以1.25為比例進(jìn)行增長(zhǎng)寞宫,MemCache啟動(dòng)時(shí)可以用-f指定這個(gè)比例),那么過(guò)來(lái)一個(gè)88字節(jié)的value拉鹃,這個(gè)value將被放到2號(hào)slab中辈赋。放slab的時(shí)候,首先slab要申請(qǐng)內(nèi)存膏燕,申請(qǐng)內(nèi)存是以page為單位的钥屈,所以在放入第一個(gè)數(shù)據(jù)的時(shí)候,無(wú)論大小為多少坝辫,都會(huì)有1M大小的page被分配給該slab篷就。申請(qǐng)到page后,slab會(huì)將這個(gè)page的內(nèi)存按chunk的大小進(jìn)行切分近忙,這樣就變成了一個(gè)chunk數(shù)組竭业,最后從這個(gè)chunk數(shù)組中選擇一個(gè)用于存儲(chǔ)數(shù)據(jù)。

如果這個(gè)slab中沒(méi)有chunk可以分配了怎么辦及舍,如果MemCache啟動(dòng)沒(méi)有追加-M(禁止LRU未辆,這種情況下內(nèi)存不夠會(huì)報(bào)Out Of Memory錯(cuò)誤),那么MemCache會(huì)把這個(gè)slab中最近最少使用的chunk中的數(shù)據(jù)清理掉锯玛,然后放上最新的數(shù)據(jù)咐柜。針對(duì)MemCache的內(nèi)存分配及回收算法,總結(jié)三點(diǎn):

1攘残、MemCache的內(nèi)存分配chunk里面會(huì)有內(nèi)存浪費(fèi)拙友,88字節(jié)的value分配在128字節(jié)(緊接著大的用)的chunk中,就損失了30字節(jié)歼郭,但是這也避免了管理內(nèi)存碎片的問(wèn)題

2献宫、MemCache的LRU算法不是針對(duì)全局的,是針對(duì)slab的

3实撒、應(yīng)該可以理解為什么MemCache存放的value大小是限制的姊途,因?yàn)橐粋€(gè)新數(shù)據(jù)過(guò)來(lái)涉瘾,slab會(huì)先以page為單位申請(qǐng)一塊內(nèi)存,申請(qǐng)的內(nèi)存最多就只有1M捷兰,所以value大小自然不能大于1M了

再總結(jié)MemCache的特性和限制

上面已經(jīng)對(duì)于MemCache做了一個(gè)比較詳細(xì)的解讀立叛,這里再次總結(jié)MemCache的限制和特性:

1、MemCache中可以保存的item數(shù)據(jù)量是沒(méi)有限制的贡茅,只要內(nèi)存足夠

2秘蛇、MemCache單進(jìn)程在32位機(jī)中最大使用內(nèi)存為2G,這個(gè)之前的文章提了多次了顶考,64位機(jī)則沒(méi)有限制

3赁还、Key最大為250個(gè)字節(jié),超過(guò)該長(zhǎng)度無(wú)法存儲(chǔ)

4驹沿、單個(gè)item最大數(shù)據(jù)是1MB艘策,超過(guò)1MB的數(shù)據(jù)不予存儲(chǔ)

5、MemCache服務(wù)端是不安全的渊季,比如已知某個(gè)MemCache節(jié)點(diǎn)朋蔫,可以直接telnet過(guò)去,并通過(guò)flush_all讓已經(jīng)存在的鍵值對(duì)立即失效

6却汉、不能夠遍歷MemCache中所有的item驯妄,因?yàn)檫@個(gè)操作的速度相對(duì)緩慢且會(huì)阻塞其他的操作

7、MemCache的高性能源自于兩階段哈希結(jié)構(gòu):第一階段在客戶端合砂,通過(guò)Hash算法根據(jù)Key值算出一個(gè)節(jié)點(diǎn)青扔;第二階段在服務(wù)端,通過(guò)一個(gè)內(nèi)部的Hash算法翩伪,查找真正的item并返回給客戶端微猖。從實(shí)現(xiàn)的角度看,MemCache是一個(gè)非阻塞的幻工、基于事件的服務(wù)器程序

8励两、MemCache設(shè)置添加某一個(gè)Key值的時(shí)候,傳入expiry為0表示這個(gè)Key值永久有效囊颅,這個(gè)Key值也會(huì)在30天之后失效当悔,見(jiàn)memcache.c的源代碼:

#define REALTIME_MAXDELTA 60*60*24*30staticrel_time_t realtime(consttime_t exptime) {if(exptime == 0)return0;if(exptime >REALTIME_MAXDELTA) {if(exptime <=process_started)return(rel_time_t)1;return(rel_time_t)(exptime -process_started);

}else{return(rel_time_t)(exptime +current_time);

}

}

這個(gè)失效的時(shí)間是memcache源碼里面寫(xiě)的,開(kāi)發(fā)者沒(méi)有辦法改變MemCache的Key值失效時(shí)間為30天這個(gè)限制

MemCache指令匯總

上面說(shuō)過(guò)踢代,已知MemCache的某個(gè)節(jié)點(diǎn)盲憎,直接telnet過(guò)去,就可以使用各種命令操作MemCache了胳挎,下面看下MemCache有哪幾種命令:

命 ? ?令作 ? ?用

get返回Key對(duì)應(yīng)的Value值

add添加一個(gè)Key值饼疙,沒(méi)有則添加成功并提示STORED,有則失敗并提示NOT_STORED

set無(wú)條件地設(shè)置一個(gè)Key值慕爬,沒(méi)有就增加窑眯,有就覆蓋屏积,操作成功提示STORED

replace按照相應(yīng)的Key值替換數(shù)據(jù),如果Key值不存在則會(huì)操作失敗

stats返回MemCache通用統(tǒng)計(jì)信息(下面有詳細(xì)解讀)

stats items返回各個(gè)slab中item的數(shù)目和最老的item的年齡(最后一次訪問(wèn)距離現(xiàn)在的秒數(shù))

stats slabs返回MemCache運(yùn)行期間創(chuàng)建的每個(gè)slab的信息(下面有詳細(xì)解讀)

version返回當(dāng)前MemCache版本號(hào)

flush_all清空所有鍵值磅甩,但不會(huì)刪除items炊林,所以此時(shí)MemCache依舊占用內(nèi)存

quit關(guān)閉連接

stats指令解讀

stats是一個(gè)比較重要的指令,用于列出當(dāng)前MemCache服務(wù)器的狀態(tài)卷要,拿一組數(shù)據(jù)舉個(gè)例子:

STAT pid 1023STAT uptime21069937STAT time1447235954STAT version1.4.5STAT pointer_size64STAT rusage_user1167.020934STAT rusage_system3346.933170STAT curr_connections29STAT total_connections21STAT connection_structures49STAT cmd_get49STAT cmd_set7458STAT cmd_flush0STAT get_hits7401STAT get_misses57..(delete渣聚、incr、decr僧叉、cas的hits和misses數(shù)奕枝,cas還多一個(gè)badval)

STAT auth_cmds0STAT auth_errors0STAT bytes_read22026555STAT bytes_written8930466STAT limit_maxbytes4134304000STAT accepting_conns1STAT listen_disabled_num0STAT threads4STAT bytes151255336STAT current_items57146STAT total_items580656STAT evicitions0

這些參數(shù)反映著MemCache服務(wù)器的基本信息,它們的意思是:

參 ?數(shù) ?名作 ? ? ?用

pidMemCache服務(wù)器的進(jìn)程id

uptime服務(wù)器已經(jīng)運(yùn)行的秒數(shù)

time服務(wù)器當(dāng)前的UNIX時(shí)間戳

versionMemCache版本

pointer_size當(dāng)前操作系統(tǒng)指針大小瓶堕,反映了操作系統(tǒng)的位數(shù)隘道,64意味著MemCache服務(wù)器是64位的

rusage_user進(jìn)程的累計(jì)用戶時(shí)間

rusage_system進(jìn)程的累計(jì)系統(tǒng)時(shí)間

curr_connections當(dāng)前打開(kāi)著的連接數(shù)

total_connections當(dāng)服務(wù)器啟動(dòng)以后曾經(jīng)打開(kāi)過(guò)的連接數(shù)

connection_structures服務(wù)器分配的連接構(gòu)造數(shù)

cmd_getget命令總請(qǐng)求次數(shù)

cmd_setset命令總請(qǐng)求次數(shù)

cmd_flushflush_all命令總請(qǐng)求次數(shù)

get_hits總命中次數(shù),重要捞烟,緩存最重要的參數(shù)就是緩存命中率薄声,以get_hits / (get_hits + get_misses)表示当船,比如這個(gè)緩存命中率就是99.2%

get_misses總未命中次數(shù)

auth_cmds認(rèn)證命令的處理次數(shù)

auth_errors認(rèn)證失敗的處理次數(shù)

bytes_read總讀取的字節(jié)數(shù)

bytes_written總發(fā)送的字節(jié)數(shù)

limit_maxbytes分配給MemCache的內(nèi)存大刑饣(單位為字節(jié))

accepting_conns是否已經(jīng)達(dá)到連接的最大值,1表示達(dá)到德频,0表示未達(dá)到

listen_disabled_num統(tǒng)計(jì)當(dāng)前服務(wù)器連接數(shù)曾經(jīng)達(dá)到最大連接的次數(shù)苍息,這個(gè)次數(shù)應(yīng)該為0或者接近于0,如果這個(gè)數(shù)字不斷增長(zhǎng)壹置, 就要小心我們的服務(wù)了

threads當(dāng)前MemCache總線程數(shù)竞思,由于MemCache的線程是基于事件驅(qū)動(dòng)機(jī)制的,因此不會(huì)一個(gè)線程對(duì)應(yīng)一個(gè)用戶請(qǐng)求

bytes當(dāng)前服務(wù)器存儲(chǔ)的items總字節(jié)數(shù)

current_items當(dāng)前服務(wù)器存儲(chǔ)的items總數(shù)量

total_items自服務(wù)器啟動(dòng)以后存儲(chǔ)的items總數(shù)量

stats slab指令解讀

如果對(duì)上面的MemCache存儲(chǔ)機(jī)制比較理解了钞护,那么我們來(lái)看一下各個(gè)slab中的信息盖喷,還是拿一組數(shù)據(jù)舉個(gè)例子:

1STAT1:chunk_size 962...3STAT 2:chunk_size 1444STAT 2:chunks_per_page 72815STAT 2:total_pages 76STAT 2:total_chunks 509677STAT 2:used_chunks 451978STAT 2:free_chunks 19STAT 2:free_chunks_end 576910STAT 2:mem_requested 608463811STAT 2:get_hits 4808412STAT 2:cmd_set 5958827113STAT 2:delete_hits 014STAT 2:incr_hits 015STAT 2:decr_hits 016STAT 2:cas_hits 017STAT 2:cas_badval 018...19STAT 3:chunk_size 21620...

首先看到,第二個(gè)slab的chunk_size(144)/第一個(gè)slab的chunk_size(96)=1.5难咕,第三個(gè)slab的chunk_size(216)/第二個(gè)slab的chunk_size(144)=1.5课梳,可以確定這個(gè)MemCache的增長(zhǎng)因子是1.5,chunk_size以1.5倍增長(zhǎng)余佃。然后解釋下字段的含義:

參 ?數(shù) ?名作 ? ? ?用

chunk_size當(dāng)前slab每個(gè)chunk的大小暮刃,單位為字節(jié)

chunks_per_page每個(gè)page可以存放的chunk數(shù)目,由于每個(gè)page固定為1M即1024*1024字節(jié)爆土,所以這個(gè)值就是(1024*1024/chunk_size)

total_pages分配給當(dāng)前slab的page總數(shù)

total_chunks當(dāng)前slab最多能夠存放的chunk數(shù)椭懊,這個(gè)值是total_pages*chunks_per_page

used_chunks已經(jīng)被分配給存儲(chǔ)對(duì)象的chunks數(shù)目

free_chunks曾經(jīng)被使用過(guò)但是因?yàn)檫^(guò)期而被回收的chunk數(shù)

free_chunks_end新分配但還沒(méi)有被使用的chunk數(shù),這個(gè)值不為0則說(shuō)明當(dāng)前slab從來(lái)沒(méi)有出現(xiàn)過(guò)容量不夠的時(shí)候

mem_requested當(dāng)前slab中被請(qǐng)求用來(lái)存儲(chǔ)數(shù)據(jù)的內(nèi)存空間字節(jié)總數(shù)步势,(total_chunks*chunk_size)-mem_requested表示有多少內(nèi)存在當(dāng)前slab中是被閑置的氧猬,這包括未用的slab+使用的slab中浪費(fèi)的內(nèi)存

get_hits當(dāng)前slab中命中的get請(qǐng)求數(shù)

cmd_set當(dāng)前slab中接收的所有set命令請(qǐng)求數(shù)

delete_hits當(dāng)前slab中命中的delete請(qǐng)求數(shù)

incr_hits當(dāng)前slab中命中的incr請(qǐng)求數(shù)

decr_hits當(dāng)前slab中命中的decr請(qǐng)求數(shù)

cas_hits當(dāng)前slab中命中的cas請(qǐng)求數(shù)

cas_badval當(dāng)前slab中命中但是更新失敗的cas請(qǐng)求數(shù)

看到這個(gè)命令的輸出量很大背犯,所有信息都很有作用。舉個(gè)例子吧盅抚,比如第一個(gè)slab中使用的chunks很少媳板,第二個(gè)slab中使用的chunks很多,這時(shí)就可以考慮適當(dāng)增大MemCache的增長(zhǎng)因子了泉哈,讓一部分?jǐn)?shù)據(jù)落到第一個(gè)slab中去蛉幸,適當(dāng)平衡兩個(gè)slab中的內(nèi)存,避免空間浪費(fèi)丛晦。

MemCache的Java實(shí)現(xiàn)實(shí)例

講了這么多奕纫,作為一個(gè)Java程序員,怎么能不寫(xiě)寫(xiě)MemCache的客戶端的實(shí)現(xiàn)呢烫沙?MemCache的客戶端有很多第三方j(luò)ar包提供了實(shí)現(xiàn)匹层,其中比較好的當(dāng)屬XMemCached了,XMemCached具有效率高锌蓄、IO非阻塞升筏、資源耗費(fèi)少、支持完整的協(xié)議瘸爽、允許設(shè)置節(jié)點(diǎn)權(quán)重您访、允許動(dòng)態(tài)增刪節(jié)點(diǎn)、支持JMX剪决、支持與Spring框架集成灵汪、使用連接池、可擴(kuò)展性好等諸多優(yōu)點(diǎn)柑潦,因而被廣泛使用享言。這里利用XMemCache寫(xiě)一個(gè)簡(jiǎn)單的MemCache客戶單實(shí)例,也沒(méi)有驗(yàn)證過(guò)渗鬼,純屬拋磚引玉:

publicclassMemCacheManager

{privatestaticMemCacheManager instance =newMemCacheManager();/**XMemCache允許開(kāi)發(fā)者通過(guò)設(shè)置節(jié)點(diǎn)權(quán)重來(lái)調(diào)節(jié)MemCache的負(fù)載览露,設(shè)置的權(quán)重越高,該MemCache節(jié)點(diǎn)存儲(chǔ)的數(shù)據(jù)越多譬胎,負(fù)載越大*/privatestaticMemcachedClientBuilder mcb =newXMemcachedClientBuilder(AddrUtil.getAddresses("127.0.0.1:11211 127.0.0.2:11211 127.0.0.3:11211"),newint[]{1, 3, 5});privatestaticMemcachedClient mc =null;/**初始化加載客戶端MemCache信息*/static{

mcb.setCommandFactory(newBinaryCommandFactory());//使用二進(jìn)制文件mcb.setConnectionPoolSize(10);//連接池個(gè)數(shù)差牛,即客戶端個(gè)數(shù)try{

mc=mcb.build();

}catch(IOException e)

{

e.printStackTrace();

}

}privateMemCacheManager()

{

}publicMemCacheManager getInstance()

{returninstance;

}/**向MemCache服務(wù)器設(shè)置數(shù)據(jù)*/publicvoidset(String key,intexpiry, Object obj)throwsException

{

mc.set(key, expiry, obj);

}/**從MemCache服務(wù)器獲取數(shù)據(jù)*/publicObject get(String key)throwsException

{returnmc.get(key);

}/*** MemCache通過(guò)compare and set即cas協(xié)議實(shí)現(xiàn)原子更新,類(lèi)似樂(lè)觀鎖银择,每次請(qǐng)求存儲(chǔ)某個(gè)數(shù)據(jù)都要附帶一個(gè)cas值多糠,MemCache

* 比對(duì)這個(gè)cas值與當(dāng)前存儲(chǔ)數(shù)據(jù)的cas值是否相等,如果相等就覆蓋老數(shù)據(jù)浩考,如果不相等就認(rèn)為更新失敗夹孔,這在并發(fā)環(huán)境下特別有用*/publicbooleanupdate(String key, Integer i)throwsException

{

GetsResponse result =mc.gets(key);longcas =result.getCas();//嘗試更新key對(duì)應(yīng)的valueif(!mc.cas(key, 0, i, cas))

{returnfalse;

}returntrue;

}

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市奸焙,隨后出現(xiàn)的幾起案子狂票,更是在濱河造成了極大的恐慌型将,老刑警劉巖纸淮,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異梳杏,居然都是意外死亡们童,警方通過(guò)查閱死者的電腦和手機(jī)权谁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)拍鲤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)贴谎,“玉大人,你說(shuō)我怎么就攤上這事季稳∩谜猓” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵景鼠,是天一觀的道長(zhǎng)仲翎。 經(jīng)常有香客問(wèn)我,道長(zhǎng)铛漓,這世上最難降的妖魔是什么溯香? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮浓恶,結(jié)果婚禮上玫坛,老公的妹妹穿的比我還像新娘。我一直安慰自己问顷,他們只是感情好昂秃,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布禀梳。 她就那樣靜靜地躺著杜窄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪算途。 梳的紋絲不亂的頭發(fā)上塞耕,一...
    開(kāi)封第一講書(shū)人閱讀 51,165評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音嘴瓤,去河邊找鬼扫外。 笑死,一個(gè)胖子當(dāng)著我的面吹牛廓脆,可吹牛的內(nèi)容都是我干的筛谚。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼停忿,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼驾讲!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤吮铭,失蹤者是張志新(化名)和其女友劉穎时迫,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體谓晌,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡掠拳,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了纸肉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片溺欧。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖柏肪,靈堂內(nèi)的尸體忽然破棺而出胧奔,到底是詐尸還是另有隱情,我是刑警寧澤预吆,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布龙填,位于F島的核電站,受9級(jí)特大地震影響拐叉,放射性物質(zhì)發(fā)生泄漏岩遗。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一凤瘦、第九天 我趴在偏房一處隱蔽的房頂上張望宿礁。 院中可真熱鬧,春花似錦蔬芥、人聲如沸梆靖。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)返吻。三九已至,卻和暖如春乎婿,著一層夾襖步出監(jiān)牢的瞬間测僵,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工谢翎, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留捍靠,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓森逮,卻偏偏與公主長(zhǎng)得像榨婆,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子褒侧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

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