您好,登錄后才能下訂單哦!
memcached 是高性能的分布式內存緩存服務器。一般的使用目的是,通過緩存數據庫查詢結果,減少數據庫訪問次數,以提高動態 Web 應用的速度、提高可擴展性。很顯然,弄清楚它的內存存儲,很有必要。還是那句話,不需要兜書包了,把自己整理的相關memcached內存管理方面的框架圖分享一下。
個人喜歡把內存管理,分為3個學習單元。
如何分配內存?
如何回收內存?
如何監控內存?
當然,本文的主要演練重點也有了。
內存如何分配
內存如何回收
認識監控參數
驗證一些邊界數據
1.如何分配內存?
1.1 默認啟動內存分配情況
這段輸出日志,可以分成2部分閱讀。第一部分是slab內存分配信息;第二個:啟用監聽情況。
有3點沒太搞清楚。
為什么每次啟動都是2個"send buffer....",而且都是28,32。
每個server listening前面的26-35的數字編號是何含義?為什么不從0開始。
括號里面的udp,是說明監聽UDP類型協議嗎?監聽TCP協議監聽呢呢?
有對這一塊比較清楚的麻煩指導下,但還好不清楚這幾點不影響大局。
1.2 自定義啟動規則
接下來,通過修改下啟動參數,看下輸出的日志。對比學習下。
通過對比,我們很容易理解一些基本概念。chunk size,增長因子。
值得一提的的有一個指標。
## -t 4時,監控curr_connections ## 4*2+2=10 [root@hadoop1 hadoop]# echo stats | nc 127.0.0.1 11211 |grep connection STAT curr_connections 10 ## -t 2時,監控curr_connections ## 2*2+2=6 [root@hadoop1 hadoop]# echo stats | nc 127.0.0.1 11211 |grep connection STAT curr_connections 6
3. 監控保存數據前后slab信息
保存數據之前監控slabs信息如下
[root@hadoop1 hadoop]# echo stats slabs | nc 127.0.0.1 11211 STAT active_slabs 0 STAT total_malloced 0
保存數據之后監控slabs信息如下
set key 1 1 1 1 STORED set key2 1 0 1 1 STORED set key2 1 0 1 1 STORED set key3 1 0 1 3 STORED [root@hadoop1 hadoop]# echo stats slabs | nc 127.0.0.1 11211 STAT 1:chunk_size 80 STAT 1:chunks_per_page 13107 STAT 1:total_pages 1 STAT 1:total_chunks 13107 STAT 1:used_chunks 2 STAT 1:free_chunks 13105 STAT 1:free_chunks_end 0 STAT 1:mem_requested 108 STAT 1:get_hits 0 STAT 1:cmd_set 4 STAT 1:delete_hits 0 STAT 1:incr_hits 0 STAT 1:decr_hits 0 STAT 1:cas_hits 0 STAT 1:cas_badval 0 STAT 1:touch_hits 0 STAT active_slabs 1 STAT total_malloced 1048560 END
通過分析日志,可以很清楚的知道,發起的操作記錄。
共發起了4個set或add操作.使用了2個大小為80的chunk。
值得一提下,保存的數據都非常小,卻占用了160字節。好心疼浪費的存儲空間啊。
通過監控total_malloced指標,還驗證了,memcached采用預分配,分組管理方式。
當真正有數據保存時,才真正分配內存空間。而且,只有slab class被使用了之后,才能通過stat slabs監控到。
2.內存如何回收
內存回收不太方便驗證,LRU算法使用情況,我們可以從側面驗證下。
我的演練思路:批量添加等大小的數據。然后dump出想要數據,確認下最小的KEY。
雖然簡單粗暴,但大體可以說明LRU算法吧。
2.1 準備批量添加數據代碼
使用的是《memcached演練(2) 訪問memcached服務 》提到的spymemcached
public void test111() throws ExecutionException, InterruptedException { final MemcachedClient mcc = MemcachedUtil.getSpyMemcachedClient(); final Lock lock = new ReentrantLock(); final String value="abcdef....."; //不停的set值 Thread t1= new Thread(new Runnable() { @Override public void run() { for(int i=0;i<10000000;i++){ // System.out.println("i="+i); try { TimeUnit.MILLISECONDS.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } String key = "lrutestkey_"+StringUtils.leftPad(""+i,10,"0");; mcc.set(key, 19000, value); } } },"setting data"); t1.start(); t1.join(); mcc.shutdown(); }
簡單dump了幾次,片段如下
[root@hadoop1 scripts]# ./memcached-tool localhost:11211 dump |grep add |sort |head -n 10 Dumping memcache contents Number of buckets: 1 Number of items : 13512 Dumping bucket 10 - 13512 total items add lrutestkey_0000000000 0 1471172545 512 add lrutestkey_0000000001 0 1471172545 512 add lrutestkey_0000000002 0 1471172545 512 ... add lrutestkey_0000002688 0 1471172763 512 [root@hadoop1 scripts]# ./memcached-tool localhost:11211 dump |grep add |sort |head -n 10 Dumping memcache contents Number of buckets: 1 Number of items : 7530 Dumping bucket 10 - 7530 total items add lrutestkey_0000002665 0 1471172762 512 add lrutestkey_0000002670 0 1471172762 512 ... [root@hadoop1 scripts]# ./memcached-tool localhost:11211 dump |grep add |sort |head -n 10 Dumping memcache contents Number of buckets: 1 Number of items : 7530 Dumping bucket 10 - 7530 total items add lrutestkey_0000005142 0 1471172787 512 add lrutestkey_0000005143 0 1471172787 512 add lrutestkey_0000005144 0 1471172787 512 ... [root@hadoop1 scripts]# ./memcached-tool localhost:11211 dump |grep add |sort |head -n 10 Dumping memcache contents Number of buckets: 1 Number of items : 7530 Dumping bucket 10 - 7530 total items add lrutestkey_0000016755 0 1471172903 512 add lrutestkey_0000016760 0 1471172903 512 ... [root@hadoop1 scripts]# ./memcached-tool localhost:11211 dump |grep add |sort |head -n 10 Dumping memcache contents Number of buckets: 1 Number of items : 7530 Dumping bucket 10 - 7530 total items add lrutestkey_0000035102 0 1471173087 512 add lrutestkey_0000035103 0 1471173087 512 add lrutestkey_0000035110 0 1471173087 512 ...
對比這5個片段,dump出最小的鍵值是越來越大,這說明,隨著數據的增加,因為越小的KEY,數據越老,所以優先會被踢出。基本可以說明LRU算法邏輯。
還有一點,要說嗎,踢出數據的過程,是按時間點進行的,不是時刻進行的。
3.監控slab參數
3,1 插入了100條數據,監控結果
[root@hadoop1 scripts]# echo stats slabs | nc 127.0.0.1 11211 STAT 10:chunk_size 696 STAT 10:chunks_per_page 1506 STAT 10:total_pages 1 STAT 10:total_chunks 1506 STAT 10:used_chunks 100 STAT 10:free_chunks 1406 STAT 10:free_chunks_end 0 STAT 10:mem_requested 58400 STAT 10:get_hits 0 STAT 10:cmd_set 100 STAT 10:delete_hits 0 STAT 10:incr_hits 0 STAT 10:decr_hits 0 STAT 10:cas_hits 0 STAT 10:cas_badval 0 STAT 10:touch_hits 0 STAT active_slabs 1 STAT total_malloced 1048176 END
3.2 調用memcached-tool dump數據
[root@hadoop1 scripts]# ./memcached-tool localhost:11211 dump |grep add |sort |head -n 10 Dumping memcache contents Number of buckets: 1 Number of items : 100 Dumping bucket 10 - 100 total items add lrutestkey_0000000000 0 1471173457 512 ...
3.3 stats slabs監控結果
[hadoop@hadoop1 ~]$ echo stats slabs | nc 127.0.0.1 11211 STAT 10:chunk_size 696 STAT 10:chunks_per_page 1506 STAT 10:total_pages 1 STAT 10:total_chunks 1506 STAT 10:used_chunks 100 STAT 10:free_chunks 1406 STAT 10:free_chunks_end 0 STAT 10:mem_requested 58400 STAT 10:get_hits 100 STAT 10:cmd_set 100 STAT 10:delete_hits 0 STAT 10:incr_hits 0 STAT 10:decr_hits 0 STAT 10:cas_hits 0 STAT 10:cas_badval 0 STAT 10:touch_hits 0 STAT active_slabs 1 STAT total_malloced 1048176 END
結果
memcached-tool 引起了get_hits 的從原來的0變成100;由于,批量添加的100條數據值均是512字節長度。 加上item的長度32,等于544. 再加上key的長度21, 一共是563.
所以會放到slab class 10() chunk size 696 ),而不是放到slab class 9(chunk size 552)。
3.4 memcached-tool監控
3.4.1準備測試數據
public void test111() throws ExecutionException, InterruptedException { final MemcachedClient mcc = MemcachedUtil.getSpyMemcachedClient(); final Lock lock = new ReentrantLock(); Thread t1= new Thread(new Runnable() { @Override public void run() { for(int i=0;i<1000;i++){ // System.out.println("i="+i); try { TimeUnit.MILLISECONDS.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } String key = "lrutestkey_"+StringUtils.leftPad(""+i,10,"0"); int size =new Random().nextInt(1000); String value = RandomStringUtils.randomAlphanumeric(size); mcc.set(key, 19000, value); System.out.println(key+"-->"+value); } } },"setting data"); t1.start(); t1.join(); mcc.shutdown(); }
3.4.2 運行memcached-tool命令
[hadoop@hadoop1 scripts]$ ./memcached-tool localhost:11211 # Item_Size Max_age Pages Count Full? Evicted Evict_Time OOM 1 80B 23s 1 10 yes 0 0 0 2 104B 23s 1 26 yes 0 0 0 3 136B 24s 1 30 yes 0 0 0 4 176B 22s 1 37 yes 0 0 0 5 224B 24s 1 47 yes 0 0 0 6 280B 24s 1 50 yes 0 0 0 7 352B 24s 1 72 yes 0 0 0 8 440B 24s 1 93 yes 0 0 0 9 552B 24s 1 91 yes 0 0 0 10 696B 24s 1 142 yes 0 0 0 11 872B 24s 1 174 yes 0 0 0 12 1.1K 24s 1 228 yes 0 0 0 [hadoop@hadoop1 scripts]$ ./memcached-tool localhost:11211 display # Item_Size Max_age Pages Count Full? Evicted Evict_Time OOM 1 80B 361s 1 10 yes 0 0 0 2 104B 361s 1 26 yes 0 0 0 3 136B 362s 1 30 yes 0 0 0 4 176B 360s 1 37 yes 0 0 0 5 224B 362s 1 47 yes 0 0 0 6 280B 362s 1 50 yes 0 0 0 7 352B 362s 1 72 yes 0 0 0 8 440B 362s 1 93 yes 0 0 0 9 552B 362s 1 91 yes 0 0 0 10 696B 362s 1 142 yes 0 0 0 11 872B 362s 1 174 yes 0 0 0 12 1.1K 362s 1 228 yes 0 0 0
可以很清楚數據分布情況,把所有的Count列值求和,正好是1000.
當然用 echo stats slabs | nc 127.0.0.1 11211 |grep used_chunks命令也可以,片段如下
[hadoop@hadoop1 scripts]$ echo stats slabs | nc 127.0.0.1 11211 |grep used_chunks STAT 1:used_chunks 10 STAT 2:used_chunks 26 STAT 3:used_chunks 30 STAT 4:used_chunks 37 STAT 5:used_chunks 47 STAT 6:used_chunks 50 STAT 7:used_chunks 72 STAT 8:used_chunks 93 STAT 9:used_chunks 91 STAT 10:used_chunks 142 STAT 11:used_chunks 174 STAT 12:used_chunks 228
./memcached-tool localhost:11211 stats 與 echo stats | nc 127.0.0.1 11211 |sort命令類似
每個指標的含義,網上資料有很多了,而且通過名稱也能猜出個所以然了。
4.驗證一些邊界數據
1. 如果key超過250,報錯信息
java.lang.IllegalArgumentException: Key is too long (maxlen = 250)
2. 可以往memcached存儲該對象。new byte[100*1024*1024]。明顯超過1M了,搞不太清楚。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。