Memcached の free_memory を使い果たした等のいざというときに抑えておきたいインフラエンジニアが問題を把握するためにまとめたものです。
Redis と同じように key を消したら治るかなと思っても治らない とならないように、Memcached がどういったメモリ管理をしているのか、操作方法を調べました。
memcached-tool host:11211
- Item 毎の統計
$ memcached-tool host:11211
# Item_Size Max_age Pages Count Full? Evicted Evict_Time OOM
1 96B 2592s 36 385809 no 0 0 0
2 120B 2009s 180 1565358 no 0 0 0
3 152B 12340223s 3380 23315240 yes 64574 9477475 0
4 192B 2397s 16 86704 no 0 0 0
5 240B 4025s 10 43348 no 0 0 0
6 304B 37589s 8 26855 no 0 0 0
7 384B 47515s 7 17352 no 0 0 0
8 480B 66223s 6 11697 no 0 0 0
9 600B 28780s 6 8375 no 0 0 0
10 752B 1927s 95 61493 no 0 0 0
11 944B 36268s 633 702630 yes 572 21781327 0
12 1.2K 55151s 1989 1760264 no 5244 21762430 0
13 1.4K 7247718s 9 2159 no 0 0 0
14 1.8K 11580483s 2 441 no 0 0 0
15 2.3K 10254258s 2 351 no 0 0 0
16 2.8K 21727816s 2 429 no 0 0 0
17 3.5K 21724300s 5 1034 no 0 0 0
18 4.4K 21723768s 3 514 no 0 0 0
19 5.5K 21724292s 3 435 no 0 0 0
20 6.9K 21725877s 4 418 no 0 0 0
21 8.7K 21725833s 4 378 no 0 0 0
22 10.8K 21727277s 4 329 no 0 0 0
23 13.6K 21729927s 4 285 no 0 0 0
24 16.9K 21729517s 5 205 no 0 0 0
25 21.2K 21727119s 5 188 no 0 0 0
26 26.5K 21730281s 5 184 no 0 0 0
27 33.1K 21723728s 6 168 no 0 0 0
28 41.4K 21731332s 9 191 no 0 0 0
29 51.7K 21730647s 6 101 no 0 0 0
30 64.7K 21738387s 4 40 no 0 0 0
31 80.9K 21732714s 4 29 no 0 0 0
32 101.1K 21785131s 4 23 no 0 0 0
33 126.3K 21732741s 3 18 no 0 0 0
34 157.9K 21794161s 3 7 no 0 0 0
35 197.4K 21794146s 5 7 no 0 0 0
36 246.8K 21794235s 4 10 no 0 0 0
37 308.5K 21794219s 3 5 no 0 0 0
38 385.6K 21794309s 4 1 no 0 0 0
表示項目 | 内容 |
---|---|
# | Item の番号 |
Item_Size | チャンクのサイズ |
Max_age | スラブの中でもっとも古いデータの期間 |
Pages | スラブに割り当てられたページ数 |
Count | スラブ内のレコード数 |
Full? | 空きチャンクの有無 |
Evicted | 有効期限切れ前に削除された数 |
Evict_Time | 最後の追い出しからの期間 |
OOM | 値をスラブに格納できなかった数(-Mオプション指定時のみ) |
なるほど、これだけではわからん。
Memcached メモリを整理して再利用する Slab Allocation メカニズムを知る
http://gihyo.jp/dev/feature/01/memcached/0002?page=1 がすごくわかりやすいです
Slab Allocationの仕組みは簡素で,確保したメモリをさまざまなサイズの固まり(chunk)に分けて,同じサイズの固まりをクラス(chunkの集合,またはchunkのサイズを定めるクラス)に整理します
また,slab allocatorには「確保したメモリは再利用する」という目標もあります。したがって,memcachedは一度確保したメモリは解放せず,常にchunkを再利用します。
Slab Allocatorの主な用語
- Page
デフォルトで1MB確保され,Slabに割り当てられるメモリ領域。Slabに割り当てられた後に,slabのサイズに応じたchunkに切り分けられる。
- Chunk
レコードをキャッシュするためのメモリ領域。
- Slab Class
特定のサイズのchunkをまとめるクラス。
改めて memcached-tool
でもう一度観てみる
$ memcached-tool host:11211
# Item_Size Max_age Pages Count Full? Evicted Evict_Time OOM
1 96B 2592s 36 386380 no 0 0 0
2 120B 2009s 180 1568707 no 0 0 0
3 152B 13019692s 3380 12983397 no 68273 8800124 0
4 192B 2397s 16 86910 no 0 0 0
5 240B 4025s 10 43443 no 0 0 0
6 304B 37589s 8 26968 no 0 0 0
7 384B 47515s 7 17403 no 0 0 0
8 480B 66223s 6 11744 no 0 0 0
9 600B 28780s 6 8399 no 0 0 0
10 752B 1927s 95 61508 no 0 0 0
11 944B 327275s 633 702630 yes 16605 21521262 0
12 1.2K 315557s 1989 1760265 yes 20207 21532979 0
13 1.4K 7247718s 9 2153 no 0 0 0
14 1.8K 11580483s 2 431 no 0 0 0
15 2.3K 10254258s 2 336 no 0 0 0
16 2.8K 21754727s 2 423 no 0 0 0
17 3.5K 21755105s 5 1008 no 0 0 0
18 4.4K 21755414s 3 506 no 0 0 0
19 5.5K 21756708s 3 420 no 0 0 0
20 6.9K 21759824s 4 413 no 0 0 0
21 8.7K 21755540s 4 410 no 0 0 0
22 10.8K 21751944s 4 339 no 0 0 0
23 13.6K 21759305s 4 279 no 0 0 0
24 16.9K 21757328s 5 200 no 0 0 0
25 21.2K 21758053s 5 198 no 0 0 0
26 26.5K 21744825s 5 181 no 0 0 0
27 33.1K 21752603s 6 165 no 0 0 0
28 41.4K 21755121s 9 204 no 0 0 0
29 51.7K 21755534s 6 95 no 0 0 0
30 64.7K 21741777s 4 41 no 0 0 0
31 80.9K 21760308s 4 30 no 0 0 0
32 101.1K 21785131s 4 24 no 0 0 0
33 126.3K 21794214s 3 18 no 0 0 0
34 157.9K 21794161s 3 7 no 0 0 0
35 197.4K 21794146s 5 7 no 0 0 0
36 246.8K 21794235s 4 10 no 0 0 0
37 308.5K 21794219s 3 5 no 0 0 0
38 385.6K 21794309s 4 2 no 0 0 0
上記の例で言うと今回に至っては、既にメモリを使い果たしている状態で、 item 番号の 3 と 11 と 12 が累計から Evict されていることがわかった。 Item(Slab) 毎の Pages が増えない限りは Count そのものも増えないことがわかった。
- item 番号の 3 については、 23315240 以上作れない
- item 番号の 11 については、 702630 以上作れない
- item 番号の 12 については、 1760265 以上作れない
状態になっており、そこだけ Evict が発生していた。
ソースコードやデータの中身から頑張って消していたが、たまたますべて Item 番号 3 のレコードを消しているとわかり、たしかに二回目見た時に Full? は no になって解決されていた。 しかし、 3 の Pages が基本的に使いまわす仕様のため、Count は減ってもそのまま保持し続けている。
そのため、 11 と 12 の Page を増やそうにも既にメモリがないため、ここに入るものはすべて Evict され続ける。 めんどくさいと思ったら再起動して全部真っさらからもう一度 Slab Allocation してもらうという手もあるが、中身を観て最適な対応をするしかなさそう。
以下、実際にどんなデータが入っているのか把握するために、コマンド操作をまとめています。
Memcached コマンド操作
専用 CLI はないため、 telnet で接続する
# telnet localhost 11211
Trying ::1...
Connected to localhost.
Escape character is '^]'.
item 一覧
stats items
item の中のキー一覧
stats cachedump [item番号] [件数]
データの格納
set key1 0 0 6
value1
STORED
- set または add というコマンドでデータを保存できる。
<command> <key> <flags> <exptime> <bytes>
<data>
- key に対して、exptime 秒間、 bytes 分の領域を確保
- key に、 data を紐付けてメモリにキャッシュ
- exptime を 0 にすると、削除が行われない
- flags はデータを圧縮するかどうかのフラグ
- 1 圧縮
- 0 非圧縮
データの取得
get key1
VALUE key1 0 6
value1
END
データの削除
delete key1
DELETED
key に対してワイルドカードがつかえない
全部消す
Memcached 上の全てのキャッシュを削除したい場合は、以下のコマンドを実行する。
flush_all
telnet 切断
quit
Connection closed by foreign host.
#