株式会社ミクシィ 研究開発グループの前坂です。前回の記事でmemcachedは分散に長けた高速なキャッシュサーバであることが紹介されました。今回はmemcachedの内部構造がどう実装されているのか、
メモリを整理して再利用するSlab Allocationメカニズム
昨今のmemcachedはデフォルトでSlab Allocatorというメカニズムを使ってメモリの確保・
Slab Allocatorの仕組みを見てみましょう。以下がmemcachedのドキュメントから引用したslab allocatorの目標です:
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.
つまりSlab Allocatorの基本は確保したメモリをあらかじめ決められたクラスサイズに応じた固定長の固まりに分けて、
Slab Allocationの仕組みは簡素で、

また、
Slab Allocatorの主な用語
- Page
デフォルトで1MB確保され、
Slabに割り当てられるメモリ領域。Slabに割り当てられた後に、 slabのサイズに応じたchunkに切り分けられる。 - Chunk
レコードをキャッシュするためのメモリ領域。
- Slab Class
特定のサイズのchunkをまとめるクラス。
Slabにレコードをキャッシュする仕組み
クライアントから送信されたデータを、
memcachedは受けとったデータのサイズを参照し、

ここまで紹介したSlab Allocatorですが、
Slab Allocatorの弱点
Slab Allocatorの開発により、
その問題は、

この問題に対する完全なソリューションは現状存在しませんが、
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.
つまり、
ただし残念なことに、
Growth Factorを使ったチューニング
memcachedはスタートアップ時にGrowth Factorという因子を指定して
では、
$ memcached -f 2 -vv
以下がスタートアップ後のverbose出力です:
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 slab class 11: chunk size 131072 perslab 8 slab class 12: chunk size 262144 perslab 4 slab class 13: chunk size 524288 perslab 2
ご覧の通り、
では、
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
ご覧の通り、
memcachedをプロダクションに導入することを検討している、
次にmemcachedのstatsを使ってslabsの利用率や色々な情報を調べる方法を紹介します。
memcachedの内部状態を調べる
memcachedにはstatsというコマンドがあり、
$ telnet ホスト ポート番号
memcachedに繋がったら、
これらのコマンドの詳しい内容は、
$ telnet localhost 11211 Trying ::1... Connected to localhost. Escape character is '^]'. stats STAT pid 481 STAT uptime 16574 STAT time 1213687612 STAT version 1.2.5 STAT pointer_size 32 STAT rusage_user 0.102297 STAT rusage_system 0.214317 STAT curr_items 0 STAT total_items 0 STAT bytes 0 STAT curr_connections 6 STAT total_connections 8 STAT connection_structures 7 STAT cmd_get 0 STAT cmd_set 0 STAT get_hits 0 STAT get_misses 0 STAT evictions 0 STAT bytes_read 20 STAT bytes_written 465 STAT limit_maxbytes 67108864 STAT threads 4 END quit
また、
$ memstat --servers=server1,server2,server3,...
libmemcachedは以下のURLから入手できます:
Slabsの使用状況を調べる
memcachedの生みの親であるBradが書いたmemcached-toolというPerlスクリプトを使うと、
使い方も至って簡単で、
$ memcached-tool ホスト:ポート オプション
Slabsの使用状況を調べるにはオプションを指定する必要がありません。したがって使用状況は以下のように取得できます:
$ memcached-tool ホスト:ポート
取得した情報は以下のように出力されます:
# Item_Size Max_age 1MB_pages Count Full? 1 104 B 1394292 s 1215 12249628 yes 2 136 B 1456795 s 52 400919 yes 3 176 B 1339587 s 33 196567 yes 4 224 B 1360926 s 109 510221 yes 5 280 B 1570071 s 49 183452 yes 6 352 B 1592051 s 77 229197 yes 7 440 B 1517732 s 66 157183 yes 8 552 B 1460821 s 62 117697 yes 9 696 B 1521917 s 143 215308 yes 10 872 B 1695035 s 205 246162 yes 11 1.1 kB 1681650 s 233 221968 yes 12 1.3 kB 1603363 s 241 183621 yes 13 1.7 kB 1634218 s 94 57197 yes 14 2.1 kB 1695038 s 75 36488 yes 15 2.6 kB 1747075 s 65 25203 yes 16 3.3 kB 1760661 s 78 24167 yes
カラムの意味は以下の通りです:
カラム | 意味 |
---|---|
# | Slab Class番号 |
Item_ | Chunkサイズ |
Max_ | LRU内で最も古いレコードの生存時間 |
1MB_ | Slabに割り当てられたページ数 |
Count | Slab内のレコード数 |
Full? | Slabに空いているchunkがあるかのフラグ |
このスクリプトで習得できる情報は設定のチューニングにとても便利なので、
メモリストレージのまとめ
今回はmemcachedのキャッシュメカニズムやチューニングを簡単にご説明させていただきました。memcachedのメモリ管理の仕組みや、
次回は今回ご説明できなかったLRUやExpireなどの仕組みに加えて、