株式会社ミクシィの前坂です。前回 はmemcached 1.4の通信面における話題を紹介いたしました。今回はmemcached 1.4で強化されたシステム運用面や監視に役立つ統計/集計システムを紹介します。
statsの機能強化
memcachedには以前からstatsというコマンドがあり、statsコマンドを特定のキャッシュサーバに発行することで、そのサーバの状態を調べることが可能でした。今回の1.4リリースでは、取得できる情報が新たに増え、システム運用者はより細かくmemcachedを監視することができるようになりました。具体的には以下の情報を得られるようになりました。
デーモンの起動オプション
スラブ単位でのアクセス記録
削除処理
インクリメント、デクリメント処理
CAS処理
重いリクエストを含んだ通信の記録
デーモンの起動オプションを取得する
キャッシュクラスタの運用者は何台もの物理サーバを管理する必要があり、すべてのサーバが同スペックであるとは限りません。したがって、立ち上がっているすべてのmemcachedデーモンが同じ設定で起動されているとは限らず、手軽にどういった設定で特定のデーモンが起動されているかを知りたいニーズが現場であるかもしれません。UNIXの場合はps(1)をつかってプロセス名を基にオプションを調べることも可能ですが、1.4からは "stats settings" というメッセージをmemcachedに送信することで、起動時の設定を取得できます。
図 telnetでコマンドを発行した例
Connected to localhost.
Escape character is '^]'.
stats settings
STAT maxbytes 67108864
STAT maxconns 1024
STAT tcpport 11211
STAT udpport 11211
STAT inter NULL
STAT verbosity 0
STAT oldest 0
STAT evictions on
STAT domain_socket NULL
STAT umask 700
STAT growth_factor 1.25
STAT chunk_size 48
STAT num_threads 5
STAT stat_key_prefix :
STAT detail_enabled no
STAT reqs_per_event 20
STAT cas_enabled yes
STAT tcp_backlog 1024
STAT binding_protocol auto-negotiate
END
スラブ単位でのアクセス記録
memcachedのキャッシュメカニズムにはスラブというさまざまのレコードサイズに対応したキャッシュ可能領域(chunk)をまとめる大きな“ 枠” が存在します。1.4で強化された統計システムでは、スラブ単位でキャッシュの状態を調べることが可能になり、より明確にサーバの健康度やアクセスされているデータを観測することができます。memcachedの内部構造に関しては過去に「memcachedのメモリストレージを理解する」という記事で紹介させていただきました。
slabの状態を調べる“ stats slabs” という“ stats” のサブコマンドは以前から存在しましたが、今回のアップデートで以下の情報が出力に追加されました。
get_hits(レコードの取得に成功した回数)
cmd_set(書き込みに成功した回数)
delete_hits(削除処理を行った回数)
incr_hits(インクリメント処理が成功した回数)
decr_hits(デクリメント処理が成功した回数)
cas_hits(CAS更新に成功した回数)
cas_badval(識別子のミスマッチによりCAS更新に失敗した回数)
上記の情報はすべてのスラブに対して個々に保持されます。このように細かくどうmemcachedのデーモンがアクセスされているかの情報を取得することにより、システム運用者はアクセスされているデータの偏りや、起動オプションのチューニングに関するヒントを得ることができます。
削除処理の統計
レコードの削除が成功、そして削除が失敗したかという二つの情報が "stats" コマンドの出力に追加されました。
delete_hits
delete_misses
delete_hitsは名前のとおり、deleteに成功した数を表しており、delete_missesは与えられた鍵に該当するデータが存在しなかった回数を表します。
インクリメント、デクリメント処理の統計
memcachedは整数を値とした既存のレコードに対して、指定された値を加算、もしくは引算を行える機能を提供してきました。あくまでキャッシュなので、ミッションクリティカルなデータに使うべきではありませんが、簡単で高速な採番機能として“ incr” と“ decr” を使えます。以下がtelnetを使った例です。
set point 0 0 1
0
STORED
incr point 1
1
incr point 100
101
decr point 50
51
上記の通り、memcachedを使えばネットワーク越しで簡単に足し算と引き算を行うことでができます。また、“ decr” コマンドで元値より大きな値を指定しても値が0以下にはならない仕様になっています。
さて、この便利な機能ですが、今回のリリースまでは、処理に関する統計を得ることができませんでした。1.4からは“ stats” コマンドの出力に以下の情報が追加されました。
incr_hits(インクリメントに成功した回数)
incr_misses(インクリメントに失敗した回数)
decr_hits(デクリメントに成功した回数)
decr_misses(デクリメントに失敗した回数)
アプリケーションでmemcachedをつかった数値系の不整合を発見した際にこの情報を使ってデバッグに役立てることができます。
CAS処理の統計
memcachedはスレッド―セーフな設計ですが、特定のレコードをアトミックに更新することを保証したいというニーズが存在します。そういったニーズに答えるために、バージョン 1.2.5以降からCAS(Compare And Swap)という仕組みが導入されました。この仕組みはもともとハードウェアの世界から来たもので、デーモンから受けとった特定のレコードに対するユニークな識別子を更新リクエストとともに送り返す仕組みです。
識別子が変更されていた場合はレコードの状態が変わっているので、更新が発生しません。完全なatomicityを実現する仕組みではないことから、コミュニティではsemi-atomicと呼んでいます。
今回の統計システム強化にはCAS系の取得可能な情報が3つ追加されました。
cas_hits (CASを使った更新の成功回数)
cas_misses(与えられた鍵に該当するレコードが存在しなかった回数)
cas_badval(レコードの状態が変更したことにより更新が失敗した回数)
重いリクエストを含んだ通信の記録
memcachedは起動時に-Rオプションを指定することで、1回の通信で連続して実行できる処理数を制限することが可能です。このオプションは特定のクライアントによりデーモンのリソースを独占されることを避ける回避法として設けられています。
特定のクライアントにデーモンを独占されるというケースは、たとえば膨大な量のmulti_getを1回の通信で行おうとした場合などです。
新たに“ stats” の出力に追加された“ conn_yields” はこういったリクエストを含んだ通信の回数を記録し、アプリケーションの最適化に役立てます。
複数台の統計情報を取得する
システム運用者は、ときにキャッシュクラスタ全体の状態を把握する必要があります。この作業は管理下にあるサーバを1台ずつ調べる、あるいはすべてのサーバ情報を取得するスクリプトを書くことで行えますが、あまり作業効率が良いとは言えません。この作業を少しでも円滑に行うために、libmemcached付属のmemstatでは最近になってクラスタ解析機能が追加されました。
使い方はとても簡単で、memstatのオプションでクラスタを組んでいるサーバリストを指定し、--analyzeオプションを指定するだけです。現状、この機能を使って取得できる情報は以下のとおりです。
クラスタにキャッシュされているレコードの平均サイズ
メモリの使用量がもっとも高いノード
使用可能のメモリ残量がもっとも低いノード
生存期間(uptime)がもっとも長いノード
クラスタから取得できたキャッシュのヒット率
以下が3台のサーバに対してクラスタ分析機能を使った例です。
$ memstat --servers=server1,server2,server3 --analyze
Memcached Cluster Analysis Report
Number of Servers Analyzed : 3
Average Item Size (incl/overhead) : 0 bytes
Node with most memory consumption : server1 (57 bytes)
Node with least free space : server1 (67108864 bytes remaining)
Node with longest uptime : server1 (220s)
Pool-wide Hit Ratio : 100%
次回予告
さて、次回で本連載の最後になります。最終回はCASの具体的な使い方、mixi での今後のmemcached運用の動向、そしてバイナリプロトコルに関して語りきれなかったトピックを紹介いたします。