Memcached性能檢測

Memcached性能檢測



——————————————————分割線————————————————————

Memcached作爲一個內存key-value存儲容器有非常優秀的性能,但是在上次的使用中確發現大量的數據丟失情況發生,導致cache的功能基本消失。具體的檢測方式如下:檢測命中率

        這個命令中比較關鍵的屬性是get_hits和get_misses,get_hits表示讀取cache命中的次數,get_misses是讀取失敗的次數,即嘗試讀取不存在的緩存數據。
         命中率=get_hits / (get_hits + get_misses)
命中率越高說明cache起到的緩存作用越大。但是在實際使用中,這個命中率不是有效數據的命中率,有些時候get操作可能只是檢查一個key存在不存在,這個時候miss也是正確的,這就像用memcached作爲一種定時器,將一些臨時數據在memcache中存放特定時間長度,業務邏輯會根據cache是否存在而作不同的邏輯,這種數據其實已經不是單純的緩存了,也不應該統計到命中率中。再者,這個命中率是從memcached啓動開始所有的請求的綜合值,不能反映一個時間段內的情況,所以要排查memcached的性能問題,還需要更詳細的數值。但是高的命中率還是能夠反映出memcached良好的使用情況,突然下跌的命中率能夠反映大量cache丟失的發生。



stats :轉儲所連接的memcached 實例的當前統計數據。

flush_all:用於清理緩存中的所有名稱/值對。如果您需要將緩存重置到乾淨的狀態,則flush_all 能提供很大的用處。

查看memcached狀態的基本命令,通過這個命令可以看到如下信息:

 

STAT pid 22459                             進程ID

STAT uptime 1027046                        服務器運行秒數

STAT time 1273043062                       服務器當前unix時間戳

STAT version 1.4.4                         服務器版本

STAT pointer_size 64                       操作系統字大小(這臺服務器是64位的)

STAT rusage_user 0.040000                  進程累計用戶時間

STAT rusage_system 0.260000                進程累計系統時間

STAT curr_connections 10                   當前打開連接數

STAT total_connections 82                  曾打開的連接總數

STAT connection_structures 13              服務器分配的連接結構數

STAT cmd_get 54                            執行get命令總數

STAT cmd_set 34                            執行set命令總數

STAT cmd_flush 3                           指向flush_all命令總數

STAT get_hits 9                            get命中次數

STAT get_misses 45                         get未命中次數

STAT delete_misses 5                       delete未命中次數

STAT delete_hits 1                         delete命中次數

STAT incr_misses 0                         incr未命中次數

STAT incr_hits 0                           incr命中次數

STAT decr_misses 0                         decr未命中次數

STAT decr_hits 0                           decr命中次數

STAT cas_misses 0    cas未命中次數

STAT cas_hits 0                            cas命中次數

STAT cas_badval 0                          使用擦拭次數

STAT auth_cmds 0

STAT auth_errors 0

STAT bytes_read 15785                      讀取字節總數

STAT bytes_written 15222                   寫入字節總數

STAT limit_maxbytes 1048576                分配的內存數(字節)

STAT accepting_conns 1                     目前接受的鏈接數

STAT listen_disabled_num 0                

STAT threads 4                             線程數

STAT conn_yields 0

STAT bytes 0                               存儲item字節數

STAT curr_items 0                          item個數

STAT total_items 34                        item總數

STAT evictions 0                           爲獲取空間刪除item的總數

 


Stats items

最後被剔除的數據在cache中存放的時間,以秒爲單位

stats items可以詳細的觀察各slab的數據對象的情況,因爲memcached的內存分配策略導致一旦memcached的總內存達到了設置的最大內存,代表所有的slab能夠使用的page都已經固定,這個時候如果還有數據放入,將開始導致memcached使用LRU策略剔除數據。而LRU策略不是針對所有的slabs,而是隻針對新數據應該被放入的slab,例如有一個新的數據要被放入slab 3,則LRU只對slab 3進行。通過stats items就可以觀察到這些剔除的情況。
具體分析如下:

evicted屬性
如果一個slab的evicted屬性不是0,則說明當前slab出現了提前剔除數據的情況,這個slab可能是你需要注意的。evicted_time屬性
如果evicted不爲0,則evicited_time就代表最後被剔除的數據時間緩存的時間。並不是發生了LRU就代碼memcached負載過載了,因爲有些時候在使用cache時會設置過期時間爲0,這樣緩存將被存放30天,如果內存慢了還持續放入數據,而這些爲過期的數據很久沒有被使用,則可能被剔除。需要注意的是,最後剔除的這個數據已經被緩存的時間,把evicted_time換算成標準時間看下是否已經達到了你可以接受的時間,例如:你認爲數據被緩存了2天是你可以接受的,而最後被剔除的數據已經存放了3天以上,則可以認爲這個slab的壓力其實可以接受的;但是如果最後被剔除的數據只被緩存了20秒,不用考慮,這個slab已經負載過重了。age屬性
age屬性反應了當前還在緩存的數據中最久的時間,它的大小和evicted_time沒有必然的大小關係,因爲可能時間最久的數據確實頻繁被讀取的,這時候不會被LRU清理掉,但是如果它小於evicted_time的話,則說明數據在被下去讀取前就被清理了,或者存放了很多長時間但是不被使用的緩存對象。Stats slabs

Stats slabs的屬性說明如下:

   
chunk_size 當前slab每個chunk的大小
chunk_per_page 每個page能夠存放的chunk數
total_pages 分配給當前slab的page總數
total_chunks 當前slab最多能夠存放的chunk數,應該等於chunck_per_page * total_page
used_chunks 已經被佔用的chunks總數
free_chunks 過期數據空出的chunk裏還沒有被使用的chunk數
free_chunks_end 新分配的但是還沒有被使用的chunk數

這個命令的信息量很大,所有屬性都很有價值。下面一一解釋各屬性:

綜合上面的數據,可以發現造成memcached的內存使用率降低的屬性有:

chunk_size, chunk_per_page
這兩個屬性是固定的,但是它反映當前slab存儲的數據大小,可以供你分析緩存數據的散列區間,通過調整增長因子可以改變slab的區間分佈,從而改變數據散列到的區域。如果大量的230byte到260byte的數據,而剛好一個slab大小是250byte,則250byte到260byte的數據將被落到下一個slab,從而導致大量的空間浪費。total_pages
這個是當前slab總共分配大的page總數,如果沒有修改page的默認大小的情況下,這個數值就是當前slab能夠緩存的數據的總大小(單位爲M)。如果這個slab的剔除非常嚴重,一定要注意這個slab的page數是不是太少了。
我上次處理的那個項目因爲和另外的一個項目共用的memcache,而且memcache已經運行了很長時間,導致page都已經全部被分配完,而剛好兩個項目的緩存數據大小差別很多,導致新項目數據最多的slab 4竟然只有一個page,所以數據緩存不到22s就被替換了,完全失去了緩存的意義。
針對我遇到的那個情況,解決方案是重新分配page,或者重啓memcache服務。但是page reassign方法從1.2.8版已經完全移除了,所以現在沒有辦法在線情況下重新分配page了。另外一種有些時候是不可以接受的,因爲一次緩存服務器的重啓將導致所有緩存的數據將重新從DB取出,這個可能造成db的壓力瞬間增大。而且有的緩存數據時不入庫的,這個時候我們就需要做memcache的導入和導出了。在下篇文章中我會總結下memcache的dump操作。total_chunks
這個的作用和total_pages基本相同,不過這個屬性可以更準確的反應實際可以存放的緩存對象總數。used_chunks, free_chunks, free_chunks_end
這三個屬性相關度比較高,從數值上來看它們滿足:
                total_chunks = used_chunks + free_chunks + free_chunks_end
used_chunks就是字面的意思,已經使用的chunk數;free_chunks卻不是所有的未被使用的chunk數,而是曾經被使用過但是因爲過期而被回收的chunk數;free_chunks_end是page中從來沒有被使用過的chunk數。


      從上圖可以看出,slab 1只放了一個對象,但是已經申請了一整個page,這個時候used_chunks爲1,但是free_chunks卻爲0,因爲還沒有任何回收的空間,而free_chunks_end卻等於10081,說明這麼多的chunk從來沒有被使用過。下圖就是這個數據過期後的stats slabs數據,可以發現free_chunks有值了,就是過期的那個chunk,所以是1,used_chunks爲0,free_chunks_end不變。


      爲什麼要分兩種free chunk呢?
      我的理解是這樣的:如果free_chunks_end不爲零,說明當前slab沒有出現過容量不夠的時候;而如果free_chunks始終爲0,說明很多數據過期時間過長或者在過期前就被剔除了,這個要結合剔除數據和數據保留的時間(age屬性)來看待。所以分開統計這兩個值可以準確的判斷實際空閒的chunk的狀態,一旦所以的chunk被使用過一次以後,除非重新申請page,否則free_chunks_end始終爲0。所以對於運行時間比較久的memcached,可能大部分這個值都是0。active_slabs, total_malloced
在stats slabs輸出的最後兩項是兩個統計數據,一個是活動的slab總數,因爲slab雖然帶編號,但是這個編號不一定是連續的,因爲有可能有些中間區間的slab沒有值就沒有初始化,這樣以後該slab有值的時候就不用改變slab的編號了。所以活動的slab總數不一定等於slab的最大編號。
total_malloced這個是實際已經分配的總內存數,單位爲byte,這個數值決定了memcached實際還能申請多少內存,如果這個值已經達到設定的上限,則不會有新的page被分配,以前分配的page也已經固定slab了。

 

    綜合上面的數據,可以發現造成memcached的內存使用率降低的屬性有:

page中從來沒有被使用過的chunks;chunk中存放數據和chunk實際大小的差值;由於短時間的數據集中在某個slab區域,導致大量page被分配,而之後被閒置的內存,這些即使有整個page的空閒也不會被分配給實際壓力很大的slab區域(這個功能是不是以後memcached會考慮實現呢?)。

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