Memcached之內存利用率提升經驗分享 轉載

 

在使用Memcached的時候,大部分人可能很少關注內存利用率,因爲Cache畢竟是Cache,那麼對於存儲數據的可靠性要求就不高,丟了也不心疼,總之能夠從DBReload回來即可,話是不錯!但是在我們的項目中,卻遇到了一個棘手的問題,就是希望數據能夠被Memcached 100%Cache起來,那麼如何讓容量規劃做到位呢,加多大內存纔是合理的,問題就隨之而來了!在我們的測試過程中,想要放入20G的數據(5000萬)到開了25GMemcached中,本想是沒有問題的,結果才放到45%的容量的時候,數據就發生了“Evict”的現象,後續再繼續追加數據,直到全部加完,Memcached的利用率始終維持在50%左右,丟了40%左右的數據,難道說需要開個50GMemcached才能搞定20G的數據存儲?這個也是不確定的,資源浪費太嚴重了,所以我們就開始着手分析原因了,目的就爲兩點:

① 100%將數據Cache起來

提高Memcached的內存利用率,節省不必要的成本,將利用率穩定在一定合理值,這樣便於將來我們預警容量問題,也能做好容量規劃

1、 首先:我們需要了解Memcached的內存分配機制:

Memcached採用了Slab Allocation機制,這種機制的好處是預先分配好內存,無需在使用時MallocFree,解決了內存碎片問題,分配好的內存也可以重複使用,所以可以減輕內存管理的負擔。

分配過程:先初始化若干個Slab,爲每個Slab分配一個Page的內存空間,Page缺省爲1MB,每個Page根據Slab規格被劃分爲若干個相同SizeChunk,每個Chunk裏保存一個Item,每個Item同時包含了Item結構體、kV,相同SizeChunk合成一組Slab Class,如圖例:

 

我們可以使用Growth Factord對分配策略進行調優,默認值是1.25Growth Factor的值不同,分配的ChunkSize就不同,且不同Slab Class中的Chunk數量也會不同,根據需要調整纔是。

n 缺省值F=1.25的情況下,Slab分配情況如下:

slab class 1: chunk size 88 perslab 11915

slab class 2: chunk size 112 perslab 9362

slab class 3: chunk size 144 perslab 7281

slab class 4: chunk size 184 perslab 5698

slab class 5: chunk size 232 perslab 4519

slab class 6: chunk size 296 perslab 3542

slab class 7: chunk size 376 perslab 2788

slab class 8: chunk size 472 perslab 2221

slab class 9: chunk size 592 perslab 1771

slab class 10: chunk size 744 perslab 1409

n F2的情況下,Slab分配情況如下:

slab class 1: chunk size 128 perslab 8192

slab class 2: chunk size 256 perslab 4096

slab class 3: chunk size 512 perslab 2048

slab class 4: chunk size 1024 perslab 1024

slab class 5: chunk size 2048 perslab 512

slab class 6: chunk size 4096 perslab 256

slab class 7: chunk size 8192 perslab 128

slab class 8: chunk size 16384 perslab 64

slab class 9: chunk size 32768 perslab 32

slab class 10: chunk size 65536 perslab 16

2、 其次,瞭解數據存儲的原理:

Memcached在收到需要存儲的數據後,先計算數據的Size,最大存入1M的數據,然後選擇適合的Slab Class中的Chunk(當然Memcached會記錄哪些Chunk是空閒的),,如圖例:

 

在數據存入選中的Slab Class,可能有以下兩種情況:

n 若該Slab Class未滿(free_chunks > 0),則成功存入;

n 若該Slab Class滿了(free_chunks0),有可能發生以下兩種情況:

l 有可用內存,則新增一個Page的內存給該Slab,該Page也是被當前Slab的同樣規格進行劃分若干Chunk,然後將數據存入新增的Chunk中;

l 無可用內存,有可能發生以下兩種情況:

u 啓用LRULRUScope只是針對Slab的,而非全局),將新數據替換老數據,老數據丟失

u 禁用LRU(追加Memcached的啓動參數-M),發生Out Of Memory錯誤

由於分配的都是定長Chunk,在內存利用率上也有天然的缺陷,如圖例:

 

n 不僅僅存在單個Chunk上浪費現象

n 而且會存在整個Slab Class浪費的現象,因爲有時遇到的數據Size根本落不到這個Slab Class上都是可能的

總之,Memcached可謂用心良苦,用空間換取性能,當然應用在使用時需要注意到這點特性,才能用好Memcached

3、 最後,就必須要對自己應用的數據Size分佈做個透徹的分析,才能將Memcached物盡其用:

根據經驗所得:

n 數據Size的分佈儘量集中可以提高Memcached的內存利用率

以我遇到的問題做爲例: 我們需要在Memcached裏保存User的操作記錄,爲了貪圖查詢的方便,我們就Key<UserID> Value<List<操作記錄>>,當每位User的操作記錄數量從1n都有分佈,那麼n較大的數據就會選擇了Size較大的Chunk進行儲存,若出現17193bytes大小的數據,那麼只能從以下兩個Slab中選擇Slab Class 25進行存儲:

slab class 24: chunk size 17192 perslab 60

slab class 25: chunk size 21496 perslab 48

如果這樣Size的數據非常多的話,那就非常杯具了,浪費的內存成(21496-17193)*m線性增長;因此我們改變了存儲策略,使用Key<操作記錄ID> = Value<操作記錄> Key<UserId> = Value<List<操作記錄 ID>>進行存儲,這樣操作記錄的每對K/VSize都在200bytes左右,結果內存利用了提升到90%左右;

n 根據ValueSize分佈,適當調整的Growth Factor也是可以提升內存利用率

n 最後,Memcached本身就是解決不可靠數據的存取服務的,做爲二級緩存是不錯的選擇,可以很大程度的提升性能,但是要想存取可靠的數據,就不能選擇Memcached,選擇一項適合的技術保障可用性纔是王道。

VN:F [1.9.6_1107]

please wait...

Rating: 0.0/10 (0 votes cast)

VN:F [1.9.6_1107]

Rating: 0 (from 0 votes)

 

» 轉載請註明來源:貳號樓肆層 » 《Memcached之內存利用率提升經驗分享》

 

發佈了99 篇原創文章 · 獲贊 0 · 訪問量 4896
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章