如圖1所示,當(dāng)往Memcached寫入500萬的160 Bytes的數(shù)據(jù)項(xiàng),內(nèi)存利用率計算:59485199(bytes)/67108864(limit_maxbytes)=89%。內(nèi)存利用率達(dá)到89%時,從evictions看到MC主動踢出很多緩存數(shù)據(jù),為什么MC達(dá)到90%的內(nèi)存利用率時開始踢出緩存數(shù)據(jù)?

要分析原因,我們首先要了解下Slab Allocation機(jī)制,可參考理解memcached的內(nèi)存存儲。
從圖2 growth factor=1.25的Slab Allocation看到,160 Bytes的數(shù)據(jù)項(xiàng)選擇192 Bytes的chunk,浪費(fèi)32 Bytes內(nèi)存。雖然Slab Allocation解決了malloc/free固有的內(nèi)存碎片問題,卻不能有效利用分配到的內(nèi)存。

我們計算每個chunk的期望內(nèi)存利用率:
120B的chunk放置的數(shù)據(jù)項(xiàng)期望長度是(96+120)/2=108,期望的內(nèi)存利用率為108/120=90%;
152B的chunk放置的數(shù)據(jù)項(xiàng)期望長度是(120+152)/2=136,期望的內(nèi)存利用率為136/152=89%;
......
n B的chunk放置的數(shù)據(jù)項(xiàng)期望長度是(n/1.25+n)/2=9n/10,期望的內(nèi)存利用率為9n/10/n=90%;
所以,內(nèi)存利用率到90%就意味growth factor=1.25的MC內(nèi)存已經(jīng)放滿數(shù)據(jù),在沒有過期數(shù)據(jù)的情況下,保存新數(shù)據(jù)只能淘汰LRU(Least Recent Used)的數(shù)據(jù)。
推廣到任意growth factor(gf),n Bytes的chunk放置的數(shù)據(jù)項(xiàng)期望長度是(n/gf+n)/2=(1+gf)n/(2*gf),期望的內(nèi)存利用率為(1+gf)/(2*gf),比如:
gf=1.25,期望的內(nèi)存利用率為90%;
gf=2,期望的內(nèi)存利用率為75%;
.......
極端情況,gf=1,期望的內(nèi)存利用率為100%,但是growth factor必須大于1,否則會如圖3的報錯。

那是不是說growth factor接近1,期望的內(nèi)存利用率就能接近100%?結(jié)果出人意料。
在分配64M內(nèi)存的MC中,growth factor=1.000001,如圖4、圖5所示,1~199個Slab class的chunk size為96 Bytes,第200個Slab class的chunk size為1MB。


當(dāng)growth factor=1.000001,往64M內(nèi)存MC插入163 Bytes的數(shù)據(jù)項(xiàng),如圖6和圖7所示,內(nèi)存利用率:bytes(10432)/limit_maxbytes(67108864)=0.01%,趨近于0。163 Bytes的數(shù)據(jù)項(xiàng)不能放入到96 Bytes的chunk,只能放到slab class 200的64MB的chunk,幾乎浪費(fèi)64M所有的空間,總共寫入163 Bytes * 64=10432 Bytes的數(shù)據(jù)。從這個例子看出,growth factor不能趨近與1,否則內(nèi)存利用率趨近于0。但是growth factor也不能太大,否則內(nèi)存利用率也會很低。
實(shí)踐經(jīng)驗(yàn)表明,growth factor最好介于1.05~2之間,并且根據(jù)業(yè)務(wù)緩存數(shù)據(jù)塊大小而定。

