memcached完全剖析系列教程《转》 memcached完全剖析系列教程–2.理解memcached的内存存储...
本文目錄
Slab?Allocation機(jī)制:整理內(nèi)存以便重復(fù)使用
·?Slab?Allocation的主要術(shù)語(yǔ)
·?在Slab中緩存記錄的原理
·?Slab?Allocator的缺點(diǎn)
·?使用Growth?Factor進(jìn)行調(diào)優(yōu)
·?查看memcached的內(nèi)部狀態(tài)
·?查看slabs的使用狀況
·?內(nèi)存存儲(chǔ)的總結(jié)
?
Slab?Allocation機(jī)制:整理內(nèi)存以便重復(fù)使用
最近的memcached默認(rèn)情況下采用了名為Slab?Allocator的機(jī)制分配、管理內(nèi)存。在該機(jī)制出現(xiàn)以前,內(nèi)存的分配是通過對(duì)所有記錄簡(jiǎn)單地進(jìn)行malloc和free來(lái)進(jìn)行的。但是,這種方式會(huì)導(dǎo)致內(nèi)存碎片,加重操作系統(tǒng)內(nèi)存管理器的負(fù)擔(dān),最壞的情況下,會(huì)導(dǎo)致操作系統(tǒng)比memcached進(jìn)程本身還慢。Slab?Allocator就是為解決該問題而誕生的。
下面來(lái)看看Slab?Allocator的原理。下面是memcached文檔中的slab?allocator的目標(biāo):
引用
the?primary?goal?of?the?slabs?subsystem?in?memcached?was?to?eliminate?memory?fragmentation?issues?totally?by?using?fixed-size?memory?chunks?coming?from?a?few?predetermined?size?classes.
也就是說(shuō),Slab?Allocator的基本原理是按照預(yù)先規(guī)定的大小,將分配的內(nèi)存分割成特定長(zhǎng)度的塊,以完全解決內(nèi)存碎片問題。
Slab?Allocation的原理相當(dāng)簡(jiǎn)單。?將分配的內(nèi)存分割成各種尺寸的塊(chunk),并把尺寸相同的塊分成組(chunk的集合)
?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
圖1:Slab?Allocation的構(gòu)造圖
而且,slab?allocator還有重復(fù)使用已分配的內(nèi)存的目的。也就是說(shuō),分配到的內(nèi)存不會(huì)釋放,而是重復(fù)利用。
Slab?Allocation的主要術(shù)語(yǔ)
Page:分配給Slab的內(nèi)存空間,默認(rèn)是1MB。分配給Slab之后根據(jù)slab的大小切分成chunk。
Chunk:用于緩存記錄的內(nèi)存空間。
Slab?Class:特定大小的chunk的組。
在Slab中緩存記錄的原理
下面說(shuō)明memcached如何針對(duì)客戶端發(fā)送的數(shù)據(jù)選擇slab并緩存到chunk中。
memcached根據(jù)收到的數(shù)據(jù)的大小,選擇最適合數(shù)據(jù)大小的slab(圖2)。?memcached中保存著slab內(nèi)空閑chunk的列表,根據(jù)該列表選擇chunk,然后將數(shù)據(jù)緩存于其中。
圖2:選擇存儲(chǔ)記錄的組的方法
實(shí)際上,Slab?Allocator也是有利也有弊。下面介紹一下它的缺點(diǎn)。
Slab?Allocator的缺點(diǎn)
Slab?Allocator解決了當(dāng)初的內(nèi)存碎片問題,但新的機(jī)制也給memcached帶來(lái)了新的問題。
這個(gè)問題就是,由于分配的是特定長(zhǎng)度的內(nèi)存,因此無(wú)法有效利用分配的內(nèi)存。例如,將100字節(jié)的數(shù)據(jù)緩存到128字節(jié)的chunk中,剩余的28字節(jié)就浪費(fèi)了(圖3)。
圖3:chunk空間的使用
對(duì)于該問題目前還沒有完美的解決方案,但在文檔中記載了比較有效的解決方案。
引用
The?most?efficient?way?to?reduce?the?waste?is?to?use?a?list?of?size?classes?that?closely?matches?(if?that’s?at?all?possible)?common?sizes?of?objects?that?the?clients?of?this?particular?installation?of?memcached?are?likely?to?store.
就是說(shuō),如果預(yù)先知道客戶端發(fā)送的數(shù)據(jù)的公用大小,或者僅緩存大小相同的數(shù)據(jù)的情況下,只要使用適合數(shù)據(jù)大小的組的列表,就可以減少浪費(fèi)。
但是很遺憾,現(xiàn)在還不能進(jìn)行任何調(diào)優(yōu),只能期待以后的版本了。但是,我們可以調(diào)節(jié)slab?class的大小的差別。接下來(lái)說(shuō)明growth?factor選項(xiàng)。
使用Growth?Factor進(jìn)行調(diào)優(yōu)
memcached在啟動(dòng)時(shí)指定?Growth?Factor因子(通過-f選項(xiàng)),就可以在某種程度上控制slab之間的差異。默認(rèn)值為1.25。但是,在該選項(xiàng)出現(xiàn)之前,這個(gè)因子曾經(jīng)固定為2,稱為“powers?of?2”策略。
讓我們用以前的設(shè)置,以verbose模式啟動(dòng)memcached試試看:
$ memcached -f 2 -vv?下面是啟動(dòng)后的verbose輸出:
slab class 1: chunk size 128 perslab 8192slab class 2: chunk size 256 perslab 4096slab class 3: chunk size 512 perslab 2048slab class 4: chunk size 1024 perslab 1024slab class 5: chunk size 2048 perslab 512slab class 6: chunk size 4096 perslab 256slab class 7: chunk size 8192 perslab 128slab class 8: chunk size 16384 perslab 64slab class 9: chunk size 32768 perslab 32slab class 10: chunk size 65536 perslab 16slab class 11: chunk size 131072 perslab 8slab class 12: chunk size 262144 perslab 4slab class 13: chunk size 524288 perslab 2?可見,從128字節(jié)的組開始,組的大小依次增大為原來(lái)的2倍。這樣設(shè)置的問題是,slab之間的差別比較大,有些情況下就相當(dāng)浪費(fèi)內(nèi)存。因此,為盡量減少內(nèi)存浪費(fèi),兩年前追加了growth?factor這個(gè)選項(xiàng)。
來(lái)看看現(xiàn)在的默認(rèn)設(shè)置(f=1.25)時(shí)的輸出(篇幅所限,這里只寫到第10組):
slab class 1: chunk size 88 perslab 11915slab class 2: chunk size 112 perslab 9362slab class 3: chunk size 144 perslab 7281slab class 4: chunk size 184 perslab 5698slab class 5: chunk size 232 perslab 4519slab class 6: chunk size 296 perslab 3542slab class 7: chunk size 376 perslab 2788slab class 8: chunk size 472 perslab 2221slab class 9: chunk size 592 perslab 1771slab class 10: chunk size 744 perslab 1409?可見,組間差距比因子為2時(shí)小得多,更適合緩存幾百字節(jié)的記錄。從上面的輸出結(jié)果來(lái)看,可能會(huì)覺得有些計(jì)算誤差,這些誤差是為了保持字節(jié)數(shù)的對(duì)齊而故意設(shè)置的。
將memcached引入產(chǎn)品,或是直接使用默認(rèn)值進(jìn)行部署時(shí),最好是重新計(jì)算一下數(shù)據(jù)的預(yù)期平均長(zhǎng)度,調(diào)整growth?factor,以獲得最恰當(dāng)?shù)脑O(shè)置。內(nèi)存是珍貴的資源,浪費(fèi)就太可惜了。
接下來(lái)介紹一下如何使用memcached的stats命令查看slabs的利用率等各種各樣的信息。
查看memcached的內(nèi)部狀態(tài)
memcached有個(gè)名為stats的命令,使用它可以獲得各種各樣的信息。執(zhí)行命令的方法很多,用telnet最為簡(jiǎn)單:
$?telnet?主機(jī)名?端口號(hào)
?
連接到memcached之后,輸入stats再按回車,即可獲得包括資源利用率在內(nèi)的各種信息。此外,輸入”stats?slabs”或”stats?items”還可以獲得關(guān)于緩存記錄的信息。結(jié)束程序請(qǐng)輸入quit。
這些命令的詳細(xì)信息可以參考memcached軟件包內(nèi)的protocol.txt文檔。
$ telnet localhost 11211Trying ::1...Connected to localhost.Escape character is '^]'.statsSTAT pid 481STAT uptime 16574STAT time 1213687612STAT version 1.2.5STAT pointer_size 32STAT rusage_user 0.102297STAT rusage_system 0.214317STAT curr_items 0STAT total_items 0STAT bytes 0STAT curr_connections 6STAT total_connections 8STAT connection_structures 7STAT cmd_get 0STAT cmd_set 0STAT get_hits 0STAT get_misses 0STAT evictions 0STAT bytes_read 20STAT bytes_written 465STAT limit_maxbytes 67108864STAT threads 4ENDquit另外,如果安裝了libmemcached這個(gè)面向C/C++語(yǔ)言的客戶端庫(kù),就會(huì)安裝?memstat?這個(gè)命令。使用方法很簡(jiǎn)單,可以用更少的步驟獲得與telnet相同的信息,還能一次性從多臺(tái)服務(wù)器獲得信息。
$?memstat?--servers=server1,server2,server3,...
?
libmemcached可以從下面的地址獲得:
http://tangent.org/552/libmemcached.html
查看slabs的使用狀況
使用memcached的創(chuàng)造著Brad寫的名為memcached-tool的Perl腳本,可以方便地獲得slab的使用情況(它將memcached的返回值整理成容易閱讀的格式)??梢詮南旅娴牡刂帆@得腳本:
http://code.sixapart.com/svn/memcached/trunk/server/scripts/memcached-tool
使用方法也極其簡(jiǎn)單:
$?memcached-tool?主機(jī)名:端口?選項(xiàng)
?
查看slabs使用狀況時(shí)無(wú)需指定選項(xiàng),因此用下面的命令即可:
$?memcached-tool?主機(jī)名:端口
?
獲得的信息如下所示:
?
# Item_Size Max_age 1MB_pages Count Full?1 104 B 1394292 s 1215 12249628 yes2 136 B 1456795 s 52 400919 yes3 176 B 1339587 s 33 196567 yes4 224 B 1360926 s 109 510221 yes5 280 B 1570071 s 49 183452 yes6 352 B 1592051 s 77 229197 yes7 440 B 1517732 s 66 157183 yes8 552 B 1460821 s 62 117697 yes9 696 B 1521917 s 143 215308 yes10 872 B 1695035 s 205 246162 yes11 1.1 kB 1681650 s 233 221968 yes12 1.3 kB 1603363 s 241 183621 yes13 1.7 kB 1634218 s 94 57197 yes14 2.1 kB 1695038 s 75 36488 yes15 2.6 kB 1747075 s 65 25203 yes16 3.3 kB 1760661 s 78 24167 yes各列的含義為:
| 列 | 含義 |
| # | slab?class編號(hào) |
| Item_Size | Chunk大小 |
| Max_age | LRU內(nèi)最舊的記錄的生存時(shí)間 |
| 1MB_pages | 分配給Slab的頁(yè)數(shù) |
| Count | Slab內(nèi)的記錄數(shù) |
| Full? | Slab內(nèi)是否含有空閑chunk |
從這個(gè)腳本獲得的信息對(duì)于調(diào)優(yōu)非常方便,強(qiáng)烈推薦使用。
內(nèi)存存儲(chǔ)的總結(jié)
本次簡(jiǎn)單說(shuō)明了memcached的緩存機(jī)制和調(diào)優(yōu)方法。希望讀者能理解memcached的內(nèi)存管理原理及其優(yōu)缺點(diǎn)。
下次將繼續(xù)說(shuō)明LRU和Expire等原理,以及memcached的最新發(fā)展方向——?可擴(kuò)充體系(pluggable?architecher)。
?
轉(zhuǎn)載于:https://www.cnblogs.com/caoheyang911016/p/4118966.html
總結(jié)
以上是生活随笔為你收集整理的memcached完全剖析系列教程《转》 memcached完全剖析系列教程–2.理解memcached的内存存储...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OpenCascade Primitiv
- 下一篇: Unity 中的协同程序