Redis関連の監視/データ分析系ツールについてメモしておきます。
随時追記予定。実務で有用なツールが他にありましたら教えていただけると嬉しいです。
環境
CentOS 5.9, Ubuntu 12.04 (x86_64)
Redis 2.6.10
(※ CentOSの6.x系への移行は足踏み状態。相当大変ですよね。。)
以下の順に紹介していきます。
- Redisコマンド
- Redis Sentinel
- Redis Live
- Redis Faina
- Redis Sampler
- redis-top
- Nagiosプラグイン
- Zabbixテンプレート
- Muninプラグイン
- Cactiプラグイン
最後のCactiプラグイン以外は実際に導入して試してみました。以降、見出しに各プロダクトへのリンクを貼っておきます。
Redisコマンド
ツール紹介の前にまずは基本から。Redisには監視やデータ解析用途で使えるコマンドがいくつか用意されています。後で紹介する各ツールはこれらのコマンドの出力を利用しているものがほとんどです。
PINGコマンド
Redisサーバに対してpingを打ちます。死活監視用。
1 2 3 4 |
PING - summary: Ping the server since: 1.0.0 group: connection |
1 2 |
redis 127.0.0.1:6379> ping PONG |
INFOコマンド
Redisサーバの設定情報とメモリ使用量など現在の各種統計情報を出力してくれます。Redisのバージョンによって項目名が変更されているので注意しておきます。
1 2 3 4 |
INFO - summary: Get information and statistics about the server since: 1.0.0 group: server |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
redis 127.0.0.1:6379> info # Server redis_version:2.6.10 redis_git_sha1:00000000 redis_git_dirty:0 redis_mode:standalone os:Linux 2.6.18-194.26.1.el5 x86_64 arch_bits:64 multiplexing_api:epoll gcc_version:4.1.2 process_id:2372 run_id:46dbab0a8655b741a1867d3b635fa45ee1f16448 tcp_port:6379 uptime_in_seconds:507476 uptime_in_days:5 lru_clock:451718 # Clients connected_clients:4 client_longest_output_list:0 client_biggest_input_buf:0 blocked_clients:0 # Memory used_memory:935016 used_memory_human:913.10K used_memory_rss:2048000 used_memory_peak:1005928 used_memory_peak_human:982.35K used_memory_lua:31744 mem_fragmentation_ratio:2.19 mem_allocator:jemalloc-3.2.0 # Persistence loading:0 rdb_changes_since_last_save:375 rdb_bgsave_in_progress:0 rdb_last_save_time:1367665923 rdb_last_bgsave_status:ok rdb_last_bgsave_time_sec:0 rdb_current_bgsave_time_sec:-1 aof_enabled:0 aof_rewrite_in_progress:0 aof_rewrite_scheduled:0 aof_last_rewrite_time_sec:-1 aof_current_rewrite_time_sec:-1 aof_last_bgrewrite_status:ok # Stats total_connections_received:118277 total_commands_processed:5737257 instantaneous_ops_per_sec:30 rejected_connections:0 expired_keys:0 evicted_keys:0 keyspace_hits:2923162 keyspace_misses:68 pubsub_channels:0 pubsub_patterns:0 latest_fork_usec:567 # Replication role:master connected_slaves:1 slave0:127.0.0.1,6380,online # CPU used_cpu_sys:208.17 used_cpu_user:85.08 used_cpu_sys_children:0.61 used_cpu_user_children:0.16 # Keyspace db0:keys=52,expires=0 |
Redisサーバが使用可能なメモリ量の上限は CONFIG GET maxmemory で取得できるので、INFOコマンドの used_memory の値を使えばメモリ使用率も計算できます。また、保存されているキーの数を調べるだけならDBSIZEコマンドも利用できます。
スレーブ側でINFOコマンドを実行した時は Replication 項目にも注目します。
1 2 3 4 5 6 7 8 9 10 |
# Replication role:slave master_host:127.0.0.1 master_port:6379 master_link_status:up master_last_io_seconds_ago:1 master_sync_in_progress:0 slave_priority:100 slave_read_only:1 connected_slaves:0 |
レプリケーションが正常に動作しているかどうかは master_link_status の項目で判断できます(up/down)。
CONFIG GETコマンド
Redisサーバの各設定パラメータ値を確認できるコマンドです。
1 2 3 4 |
CONFIG GET parameter summary: Get the value of a configuration parameter since: 2.0.0 group: server |
1 2 3 4 5 6 |
redis 127.0.0.1:6379> config get maxclients 1) "maxclients" 2) "10000" redis 127.0.0.1:6379> config get save 1) "save" 2) "900 1 300 10 60 10000" |
SLOWLOGコマンド
スロークエリログを管理するコマンドです。スロークエリだと判断するクエリ実行時間は設定ファイルの slowlog-log-slower-than で指定できます(デフォルト 10000マイクロ秒)。また、このスロークエリログはメモリ内に保存されるためファイルには書き出されません。
1 2 3 4 |
SLOWLOG subcommand [argument] summary: Manages the Redis slow queries log since: 2.2.12 group: server |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
## スロークエリログを直近の5クエリ分取得 (multi bulk replies) redis 127.0.0.1:6379> slowlog get 5 1) 1) (integer) 9 ## クエリログのID 2) (integer) 1367733604 ## ログが保存された時刻(unix timestamp) 3) (integer) 10066 ## クエリの実行時間(microseconds) 4) 1) "MGET" ## 実行したクエリ 2) "string:key:1" 3) "string:key:2" 4) "string:key:3" 2) 1) (integer) 8 2) (integer) 1367640603 3) (integer) 11052 4) 1) "INFO" 3) 1) (integer) 7 2) (integer) 1367637003 3) (integer) 10102 4) 1) "SDIFF" 2) "set:key:1" 3) "set:key:2" 4) 1) (integer) 6 2) (integer) 1367617460 3) (integer) 21928 4) 1) "SINTER" 2) "set:key:1" 3) "set:key:2" 5) 1) (integer) 5 2) (integer) 1367609407 3) (integer) 10297 4) 1) "HGETALL" 2) "hash:key" ## 取得できるスロークエリ数を取得 redis 127.0.0.1:6379> slowlog len 10 ## スロークエリログのリセット redis 127.0.0.1:6379> slowlog reset OK |
MONITORコマンド
クエリ情報をリアルタイムに出力します(tail -fのように)。このMONITORコマンドの出力情報を集めておけば、どのキーに対してどんな操作が行われたか統計をとることができます。
1 2 3 4 |
MONITOR - summary: Listen for all requests received by the server in real time since: 1.0.0 group: server |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
redis 127.0.0.1:6379> monitor OK 1367667137.041391 [0 127.0.0.1:43723] "LPOP" "list:key" 1367667137.041609 [0 127.0.0.1:43723] "LPOP" "list:key" 1367667137.041873 [0 127.0.0.1:43723] "LRANGE" "list:key" "0" "-1" 1367667137.042092 [0 127.0.0.1:43723] "DEL" "list:key" 1367667137.042318 [0 127.0.0.1:43723] "SADD" "set:key:1" "a" 1367667137.042534 [0 127.0.0.1:43723] "SADD" "set:key:2" "b" 1367667137.042764 [0 127.0.0.1:43723] "SADD" "set:key:1" "c" 1367667137.042990 [0 127.0.0.1:43723] "SADD" "set:key:2" "c" 1367667137.043202 [0 127.0.0.1:43723] "SADD" "set:key:1" "d" 1367667137.043414 [0 127.0.0.1:43723] "SADD" "set:key:2" "e" 1367667137.043625 [0 127.0.0.1:43723] "SMEMBERS" "set:key:1" 1367667137.043895 [0 127.0.0.1:43723] "SMEMBERS" "set:key:2" 1367667137.044145 [0 127.0.0.1:43723] "SINTER" "set:key:1" "set:key:2" |
実験/検証でならともかく、実際のWebサービスだと利用されるデータ型/コマンドは一部のものに偏ることが多いと思います。MONITORコマンドの全ての出力を集めてHadoopに分析させてた知人がいますけど、全データ取らなくても少量のサンプリングデータで傾向推定できるし、実務だと運用負荷増えるだけで無駄が多いよって言ったら顔真っ赤にしてました。
Redis Sentinel
Redis本家プロジェクトで開発されている、Redisサーバの死活監視/通知および自動フェイルオーバー機能を提供する管理サーバ(redis-sentinel)です。v2.4.16または2.6.0-rc6以降のバージョンから利用可能になりました。公式ドキュメントを参考にしつつ動作確認をします。
導入
最新版のRedisのソースコードをコンパイルすると src ディレクトリに redis-sentinel という名前の実行可能バイナリが出来上がりますが、実体は redis-server でファイル名が異なるだけです。
構成
ここでは2つのホストでSlaveを2プロセス、Sentinelを3プロセスの構成で試します。
* Master db0:6379
* Slave db0:6380, db1:6379
* Sentinel db0:26379, db0:23680, db1:26379
Sentinelの動作確認は公式ドキュメント APPENDIX Bの手順を参考に。
設定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
## /etc/redis/sentinel.conf # port <sentinel-port> port 26379 # sentinel monitor <master-name> <ip> <redis-port> <quorum> sentinel monitor mymaster db0 6379 2 # sentinel down-after-milliseconds <master-name> <milliseconds> sentinel down-after-milliseconds mymaster 5000 # sentinel failover-timeout <master-name> <milliseconds> sentinel failover-timeout mymaster 900000 # sentinel can-failover <master-name> <yes|no> sentinel can-failover mymaster yes # sentinel parallel-syncs <master-name> <numslaves> sentinel parallel-syncs mymaster 1 |
設定項目
各設定項目について表にしています。Sentinelによるクラスタ監視はいわゆるQuorumベース投票の方式を採ります。複数のSentinelがMasterを監視していて、その内しきい値数以上のSentinelがMasterのダウンを検知したらフェイルオーバー処理を開始します。
monitor | Masterのホストとポートおよび状態がODOWN(objectively down)に移行するための定足数(quorum) |
down-after-milliseconds | Master/Slaveのダウン検知後、状態がSDOWN(subjectively down)に移行するまでの時間(ms) |
failover-timeout | フェイルオーバー処理のタイムアウト(ms) |
can-failover | フェイルオーバー処理が実行可能か(yes/no) |
parallel-syncs | SlaveをMasterに昇格させた後、いくつのSlaveと同期させるか |
SentinelはMasterとSlave両方の死活監視をしてくれますが、状態がODOWNに遷移するのはMasterのみなので注意してください。can-failover を no にして起動したSentinelプロセスはフェイルオーバー処理自体は行わず(他のSentinelに任せる)、自身はダウン検知と投票処理のみを行います。
起動
Sentinel起動前にレプリケーションが動作していることを確認しておきます。
1 2 3 4 5 6 |
redis db0:6379> info replication # Replication role:master connected_slaves:1 slave0:db0,6380,online slave1:db1,6379,online |
続けて3つのSentinelプロセスを立ち上げます。
1 2 3 |
$ redis-sentinel /etc/redis/sentinel.conf ## または redis-server をsentinelモードで起動する $ redis-server /etc/redis/sentinel.conf --sentinel |
ログにて各SlaveおよびSentinelと接続したことを確認できます。
1 2 3 4 |
[19069] 14 May 16:30:31.909 * +slave slave db1:6379 db1 6379 @ mymaster db0 6379 [19069] 14 May 16:30:31.909 * +slave slave db0:6380 db0 6380 @ mymaster db0 6379 [19069] 14 May 16:30:38.320 * +sentinel sentinel db0:26380 db0 26380 @ mymaster db0 6379 [19069] 14 May 16:30:39.655 * +sentinel sentinel db1:26379 db1 26379 @ mymaster db0 6379 |
また、Sentinel起動後はINFOコマンドでSentinel関連の情報を確認ができます。
1 2 3 4 5 6 7 |
redis db0:26379> info sentinel # Sentinel sentinel_masters:1 sentinel_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 master0:name=mymaster,status=ok,address=db0:6379,slaves=2,sentinels=3 |
Sentinelプロセス自体の監視は一番下の項目を見るようにすれば良いかと思います。Sentinel監視のためのZabbixの設定例については後述します。
フェイルオーバー処理の動作確認の為、ここでMasterを落とします。
1 |
redis db0:6379> shutdown |
ログにてフェイルオーバー処理の進捗を確認できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
[19069] 14 May 16:30:51.170 # +sdown master mymaster db0 6379 [19069] 14 May 16:30:52.386 # +odown master mymaster db0 6379 #quorum 2/2 [19069] 14 May 16:30:52.386 # +failover-triggered master mymaster db0 6379 [19069] 14 May 16:30:52.386 # +failover-state-wait-start master mymaster db0 6379 #starting in 13910 milliseconds [19069] 14 May 16:31:06.379 # +failover-state-select-slave master mymaster db0 6379 [19069] 14 May 16:31:06.480 # +selected-slave slave db1:6379 db1 6379 @ mymaster db0 6379 [19069] 14 May 16:31:06.480 * +failover-state-send-slaveof-noone slave db1:6379 db1 6379 @ mymaster db0 6379 [19069] 14 May 16:31:06.583 * +failover-state-wait-promotion slave db1:6379 db1 6379 @ mymaster db0 6379 [19069] 14 May 16:31:06.901 # +promoted-slave slave db1:6379 db1 6379 @ mymaster db0 6379 [19069] 14 May 16:31:06.902 # +failover-state-reconf-slaves master mymaster db0 6379 [19069] 14 May 16:31:06.991 * +slave-reconf-sent slave db0:6380 db0 6380 @ mymaster db0 6379 [19069] 14 May 16:31:07.294 * +slave-reconf-inprog slave db0:6380 db0 6380 @ mymaster db0 6379 [19069] 14 May 16:31:08.316 * +slave-reconf-done slave db0:6380 db0 6380 @ mymaster db0 6379 [19069] 14 May 16:31:08.417 # +failover-end master mymaster db0 6379 [19069] 14 May 16:31:08.417 # +switch-master mymaster db0 6379 db1 6379 [19069] 14 May 16:31:08.548 * +slave slave db0:6380 db0 6380 @ mymaster db1 6379 [19069] 14 May 16:31:09.068 * +sentinel sentinel db0:26380 db0 26380 @ mymaster db1 6379 [19069] 14 May 16:31:12.258 * +sentinel sentinel db1:26379 db1 26379 @ mymaster db1 6379 |
SentinelがMasterのダウンを検知すると状態がSDOWNに、quorumパラメータで指定した数のSDOWNが揃うと次はODOWNへと遷移、その後フェイルオーバー処理が開始されます。
最後に新しいMasterとSlaveで正常稼働していることを確認します。
1 2 3 4 5 |
redis db1:6379> info replication # Replication role:master connected_slaves:1 slave0:db0,6380,online |
以上、Sentinelによるフェイルオーバー機能の動作確認まで試してみました。
Sentinel API
SentinelはいくつかのAPIを提供しているので簡単に紹介したいと思います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
## SENTINEL masters # 監視対象のMasterに関する情報を確認 redis 127.0.0.1:26379> sentinel masters 1) 1) "name" 2) "mymaster" 3) "ip" 4) "127.0.0.1" 5) "port" 6) "6379" 7) "runid" 8) "b3b31e6c6d1fbb0cec5d179fd666ce00ea103746" 9) "flags" 10) "master" 11) "pending-commands" 12) "0" 13) "last-ok-ping-reply" 14) "568" 15) "last-ping-reply" 16) "568" 17) "info-refresh" 18) "9745" 19) "num-slaves" 20) "1" 21) "num-other-sentinels" 22) "1" 23) "quorum" 24) "2" ## SENTINEL slaves <master name> # Slaveに関する情報を確認 redis 127.0.0.1:26379> sentinel slaves mymaster 1) 1) "name" 2) "127.0.0.1:6380" 3) "ip" 4) "127.0.0.1" 5) "port" 6) "6380" 7) "runid" 8) "17c0f7e7e4d2af0f5f6140ea0ceb0d82d0010aed" 9) "flags" 10) "s_down,slave,disconnected" 11) "pending-commands" 12) "0" 13) "last-ok-ping-reply" 14) "709377" 15) "last-ping-reply" 16) "709377" 17) "s-down-time" 18) "704333" 19) "info-refresh" 20) "712808" 21) "master-link-down-time" 22) "0" 23) "master-link-status" 24) "ok" 25) "master-host" 26) "127.0.0.1" 27) "master-port" 28) "6379" 29) "slave-priority" 30) "100" ## SENTINEL is-master-down-by-addr <ip> <port> # Masterの死活確認 redis 127.0.0.1:26379> sentinel is-master-down-by-addr 127.0.0.1 6379 1) (integer) 0 ## 0:UP, 1:DOWN 2) "397dec99760d5d30043941fe4c1c35ba99e99ebf" ## Sentinel(subjective leader)のrun_id ## SENTINEL get-master-addr-by-name <master name> # MasterのIP, Portを確認 redis 127.0.0.1:26379> sentinel get-master-addr-by-name mymaster 1) "127.0.0.1" 2) "6379" ## SENTINEL reset # Sentinelの現在の状態をリセット(フェイルオーバー処理中であっても) redis 127.0.0.1:26379> sentinel reset mymaster (integer) 1 |
Sentinel関連の管理ツールを作る際にはこのSentinel APIをサポートしたクライアントライブラリを使うと楽かと思います。ライブラリ側でどういった実装をすれば良いかという議論はGoogleグループの以下のトピックを参考に。
参考: Redis Sentinel: let’s improve clients detection of failover events
以下、フェイルオーバー処理の挙動に関する部分をピックアップして紹介します。
昇格させるSlaveの選択
当然ですがSlaveとして正常に稼働しているプロセスが対象となります。細かい条件を省いてざっくり言うと、Masterとの接続が安定していて(ダウンタイムが少ない)、SentinelからのPING/INFOコマンドに直近5000ms以内に応答しているSlaveが対象になります(詳細は公式ドキュメントと src/sentinel.c を参照)。
対象となるSlaveが複数ある場合は slave_priority の値が小さいSlaveを選択します。
1 2 3 4 5 6 7 8 9 10 11 |
redis db0:6380> info replication # Replication role:slave master_host:127.0.0.1 master_port:6379 master_link_status:up master_last_io_seconds_ago:0 master_sync_in_progress:0 slave_priority:100 ## <- この値 slave_read_only:1 connected_slaves:0 |
同じ slave_priority のSlaveが存在する場合は run_id が小さいSlaveを選択します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
redis db0:6380> info # Server redis_version:2.6.10 redis_git_sha1:00000000 redis_git_dirty:0 redis_mode:standalone os:Linux 2.6.18-194.26.1.el5 x86_64 arch_bits:64 multiplexing_api:epoll gcc_version:4.1.2 process_id:17468 run_id:17c0f7e7e4d2af0f5f6140ea0ceb0d82d0010aed ## <- この値 tcp_port:6380 uptime_in_seconds:1738 uptime_in_days:0 lru_clock:538965 |
2013/06現在は slave_priority の変更を行うAPIは公開されていないようですので、単に run_id が若いSlaveが選択されることになります。Slave選択のアルゴリズムは今後変更されることもあるでしょう。
Sentinels/Slavesの自動検出
Sentinelの設定にSlaveのリストを持たせる必要がないのは、SentinelがPub/Subによる情報共有を行っているからです。途中で別のSentinelやSlaveをオンラインで追加しても他のSentinelにその情報は伝わります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
## Sentinelは "__sentinel__:hello" チャンネルを利用している redis db0:6379> subscribe __sentinel__:hello Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "__sentinel__:hello" 3) (integer) 1 1) "message" 2) "__sentinel__:hello" 3) "127.0.0.1:26380:77887a367e1c76ee9dc15f67a2fb3dc49bb00bf4:1" 1) "message" 2) "__sentinel__:hello" 3) "127.0.0.1:26379:3a92da7269b69fa1dcce5915068c4af6e8caf161:1" 1) "message" 2) "__sentinel__:hello" 3) "127.0.0.1:26380:77887a367e1c76ee9dc15f67a2fb3dc49bb00bf4:1" 1) "message" 2) "__sentinel__:hello" 3) "127.0.0.1:26379:3a92da7269b69fa1dcce5915068c4af6e8caf161:1" |
メッセージの内容は host:port:run_id:can-failover となっていて、__sentinel__:hello チャンネルに5秒毎にpublish、全てのSentinelはこのチャンネルをsubscribeして情報共有しています。
レプリケーションの注意点
RedisのレプリケーションはMySQLなどのRDBMSのレプリケーションとは異なる部分が多いです。Redisはレプリケーション開始時に全てのデータをディスクに書き出してからSlaveに転送するのでI/Oやネットワーク帯域には注意してください(Redis v2.8ではPSYNC(Partial Resynchronization)が実装されるようなので、この問題は解消されると思われます)。
また、Sentinel自体まだunstableなプロダクトなので実務でもし使う場合もいろいろ注意してください(というか利用は許可されないかな)。この間、Disaster Recoveryのシミュレーションで東西の自社データセンター間を跨いだSentinelの運用検証もしてみたのですけど、いろいろとつまづいた所がありました。例えば、状態がODOWNになった時にSentinel間でPub/Subの疎通が上手く取れずにフェイルオーバー処理が開始されないケースなどが目立ちました。
あとぜんぜん関係ないですけど、redis-server 起動時のAA(アスキーアート)が全体的にブツブツしてて生理的に気持ち悪いんですけどアレなんとかならないですかね。僕はいつもアレが表示されないようにソースコードをいじってからコンパイルしてます。。
Redis Live
(Python製)
Redisのクエリ統計解析ツール、INFO/MONITORコマンドを利用しています。”Live”と名付けられているようにリアルタイム性を重視しているようです。
導入
公式ドキュメントの通りに。WebサーバはTornadoを使います。
1 2 3 4 5 6 7 8 9 10 |
## Pythonはインストール済みとする ## 依存モジュールのインストール ## (Pythonが2.7未満の場合は argparse モジュールも必要) $ pip install tornado $ pip install redis $ pip install python-dateutil ## Redis Liveのソースを取得 $ git clone https://github.com/kumarnitin/RedisLive.git $ cd RedisLive/src |
設定
設定ファイルはJSON形式でシンプル。監視対象のRedisサーバの場所と統計情報を保存するストレージの場所をそれぞれ指定します。ストレージにはRedisサーバかSQLite3ファイルを選択できます。
* redis-live.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
{ "RedisServers": [ { "server": "127.0.0.1", "port" : 6379 } ], "DataStoreType" : "redis", "RedisStatsServer": { "server" : "127.0.0.1", "port" : 6381 } } |
SQLite3に保存する場合は “DataStoreType” に “sqlite” に指定すればOKです。db/redislive.sqlite ファイルにデータが保存されるようになります。
起動
1 2 3 4 |
## モニタリングスクリプトをフォアグラウンドで起動 (120秒間監視) $ ./redis-monitor.py --duration=120 ## Webサーバを起動 $ ./redis-live.py |
あとはブラウザからRedis LiveのWebインタフェースにアクセスするだけです。デフォルトURLは http://hostname:8888/index.html なので外部から閲覧する場合は8888番ポートを開放しておきます。また、実際に運用する際には redis-monitor.py/redis-live.py は supervisor などでデーモン化して管理すると楽です。
こんな風にリアルタイムでグラフを書いてくれます。
(クリックで拡大)
ぼーっと眺めているとグラフが横に流れていくので見てて面白いです。ただし、CPU負荷がかなり高くなりますので実際に使うにはRedis Live用の監視サーバを準備する必要があります。安価なVPSなどで運用するのは難しいです。
Redis Faina
(Python製)
前述のRedis Liveと同様にMONITORコマンドを使ったクエリ統計解析ツール、Instagramで開発されました。グラフを描く機能はありませんが、Redis Liveと比較して軽量なのが嬉しいです。
導入
1 2 3 |
## Redis Fainaのスクリプトを取得 $ git clone https://github.com/Instagram/redis-faina.git $ cd redis-faina |
Redis FainaはMONITORコマンドの出力を正規表現でがんばって解析するツール。標準モジュールのみで動作し、データをディスクに書き出さずに全てオンメモリで処理するのでポータビリティが高いのがメリットです。
実行
MONITORコマンドの出力を redis-faina.py に渡すだけです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
## MONITORコマンドの出力を500行分解析する redis 127.0.0.1:6379> -p 6379 MONITOR | head -n 500 | ./redis-faina.py Overall Stats ======================================== Lines Processed 500 Commands/Sec 10.72 Overall Stats ======================================== Lines Processed 500 Commands/Sec 10.09 Top Prefixes ======================================== list 130 (26.00%) hash 126 (25.20%) set 125 (25.00%) string 100 (20.00%) worker_test 15 (3.00%) key 3 (0.60%) Top Keys ======================================== list:key 130 (26.00%) hash:key 126 (25.20%) string:key:1 90 (18.00%) set:key:1 76 (15.20%) set:key:2 49 (9.80%) string:key:2 10 (2.00%) key:hit:miss 3 (0.60%) worker_test:key:94 2 (0.40%) Top Commands ======================================== SADD 60 (12.00%) RPUSH 50 (10.00%) GET 43 (8.60%) SET 33 (6.60%) RPOP 30 (6.00%) HINCRBY 27 (5.40%) HSET 27 (5.40%) HGET 27 (5.40%) Command Time (microsecs) ======================================== Median 243.0 75% 336.0 90% 555.0 99% 3516384.0 Heaviest Commands (microsecs) ======================================== HKEYS 19652661.0 SET 14808015.75 GET 10515012.75 EXPIRE 4475457.75 SADD 18927.5 RPUSH 11937.5 RPOP 10091.5 HINCRBY 7310.0 Slowest Calls ======================================== 4002236.75 "GET" "key:hit:miss" 4001225.0 "GET" "key:hit:miss" 4001182.0 "EXPIRE" "worker_test:key:94" "3600" 3573112.0 "HKEYS" "hash:key" 3516384.0 "HKEYS" "hash:key" 3506986.0 "SET" "worker_test:key:53" "53" 3465291.0 "SET" "worker_test:key:48" "48" 3460973.75 "HKEYS" "hash:key" |
グラフ化しなくても結構見やすい出力になっています。リアルタイム性はありませんが、Redis Liveよりも手軽に利用できるのがメリットです。
Redis Sampler
(Ruby製)
各データ型毎にキーの分布情報などをランダムサンプリングによって分析するコマンドラインツール。Salvatoreさん(Redis開発者)によって書かれています。
導入
1 2 3 4 5 |
## redisモジュールをインストール $ gem install redis ## Redis Samplerのスクリプトを取得 $ git clone https://github.com/antirez/redis-sampler.git $ cd redis-sampler |
実行
redis-sampler.rb をコマンドラインから実行するだけです。僕の手持ちの環境だと良いサンプルが作れなかったので、githubのサンプルを参照してください(antirez/redis-sampler)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
## ホスト、ポート、データベース番号、標本数を指定 $ ./redis-sampler.rb localhost 6379 0 1000000 Sampling localhost:6379 DB:0 with 1000000 RANDOMKEYS TYPES ===== zset: 873268 (87.33%) string: 124995 (12.50%) set: 1022 (0.10%) hash: 576 (0.06%) list: 139 (0.01%) ## String型の標本化データ STRINGS, SIZE OF VALUES ======================= ## データ長: キー数 (比率) 6: 61222 (48.98%) 7: 17056 (13.65%) 13: 8274 (6.62%) 15: 7991 (6.39%) 5: 4629 (3.70%) 31: 3263 (2.61%) 20: 2670 (2.14%) 2: 2518 (2.01%) 27: 1675 (1.34%) 42: 1270 (1.02%) 159: 893 (0.71%) 1: 705 (0.56%) 47: 641 (0.51%) 34: 594 (0.48%) 41: 521 (0.42%) 38: 493 (0.39%) 28: 413 (0.33%) 22: 406 (0.32%) 139: 351 (0.28%) 29: 343 (0.27%) 83: 337 (0.27%) ## 平均/標準偏差/最小/最大 (suppressed 172 items with perc < 0.5% for a total of 6.98%) Average: 15.97 Standard Deviation: 26.52 Min: 0 Max: 1123 ## 2のべき乗値に量子化 Powers of two distribution: (NOTE <= p means: p/2 < x <= p) <= 8: 82913 (66.33%) <= 16: 16789 (13.43%) <= 32: 9571 (7.66%) <= 64: 6232 (4.99%) <= 128: 3333 (2.67%) <= 256: 2682 (2.15%) <= 2: 2518 (2.01%) <= 1: 740 (0.59%) <= 4: 199 (0.16%) <= 512: 14 (0.01%) <= 1024: 3 (0.00%) <= 2048: 1 (0.00%) ## ... 以下、データ型毎の分析結果が出力される |
EXPIREが設定されたキーの情報なども分析することができます。この redis-sampler.rb は小さなスクリプトなのでいろいろ拡張して使うこともできそうです。
redis-top
* redis-top というCLIを書いた
日本の方が作られたコマンドラインツール。INFOコマンドの出力を dstat コマンドのように見やすく整形表示してくれます。導入は cpanm で簡単にできます(cpanm の環境がない人はgithubからファイル群を取ってくる)。
導入/実行
1 2 3 4 5 |
## インストール $ cpanm App::RedisTop ## 実行 $ redis-top ## ブログだと表示が崩れるので出力例はスクリーンショットを |
CONFIG GET で取れる値(maxmemoryやmaxclientsなど)を使って使用率が確認できるとより便利かなぁと思います。
ここからは汎用的な監視ツールのRedis用プラグインの紹介になりますので、細かい導入手順等は省略させていただきます。
Nagiosプラグイン
(Perl製)
統合監視ツール NagiosのRedis用プラグイン、check_redis.pl を紹介します。導入は通常のNagiosプラグイン追加手順と同じ。CPANのRedisモジュールが必要なので cpanm とかであらかじめインストールしておきます。ここではNRPEで外部からのActiveチェックを試します。
1 2 3 4 5 6 7 8 9 10 11 12 |
## 監視対象ホスト (nrpe.cfg) ## 死活確認と現在のメモリ使用量、接続クライアント数を監視 command[check_redis]=/usr/lib64/nagios/plugins/check_redis.pl -H 127.0.0.1 -A used_memory,used_memory_peak,connected_clients ## Nagios稼働ホスト (remotehost.cfg) define service { use generic-service host_name rest-term.com service_description Redis check_command check_nrpe!check_redis notification_interval 0 } |
1 2 3 4 5 |
## 監視対象ホストでNRPEの再起動 $ sudo service nrpe restart ## Nagios稼働ホストでNagiosの再起動 $ sudo service nagios restart |
check_redis.pl をコマンドラインから利用
Nagiosプラグインなのでもちろんコマンドラインツールとしても利用できます。check_redis.pl は1ファイルで140KB近くもある大作で、オプションを組み合わせればいろんなことができる実装になっています。
1 2 3 4 5 6 7 |
## 死活確認、必須パラメータはホストのみ(デフォルトポート 6379) $ ./check_redis.pl -H 127.0.0.1 OK: REDIS 2.6.10 on 127.0.0.1:6379 has 1 databases (db0) with 47 keys, up 5 days 21 hours ## メモリ使用量(used_memory,used_memory_peak)を取得 $ ./check_redis.pl -H 127.0.0.1 -A used_memory,used_memory_peak OK: REDIS 2.6.10 on 127.0.0.1:6379 has 1 databases (db0) with 45 keys, up 6 days 23 hours | used_memory=935344 used_memory_peak=1005928B |
Zabbixテンプレート
Nagiosを紹介したのでこちらも。統合監視ツール ZabbixのRedis用テンプレートです。おそらく多くの方が自分の使いやすいテンプレートを作っているとは思うのですが、ここではrdvnさん作のテンプレートを紹介します。
1 2 |
## zabbix_agentd.conf に UserParameter を設定 UserParameter=redis.stat[*], /path/to/redis-cli info | grep "$1:" | cut -d ":" -f2 |
テンプレートにデフォルトで設定されているアイテムは20個ありました。
(クリックで拡大)
redis.stat[{INFOコマンドの項目}] という形式で簡単にアイテムの追加ができます。
また、最初に紹介したRedis Sentinelプロセスの監視用 UserParameter は以下のように設定しました。ただ、INFOコマンドの出力はバージョンによって変更される場合があるのでアップデート後はきちんと動作確認しておく必要があります。
1 |
UserParameter=redis.sentinel_status[*], /path/to/redis-cli -p 26379 info | grep $1 | awk -F '[,=]' '{print $$4}' |
設定したらZabbix Agentを再起動してZabbixサーバから動作確認します。
1 2 3 |
## 動作確認, 添字にはMaster名を指定 $ zabbix_get -s db0 -k 'redis.sentinel_status[mymaster]' ok |
ZabbixはNagiosと比較されることが多いですが(Zabbix vs Nagios comparison)、国内ではまだNagiosのシェアの方が高いんでしょうか。ZabbixはストレージにMySQLを使うのでZabbixサーバ管理者にはMySQL運用の知識も必要になってきます。Webインタフェースの方はNagiosよりも洗練されていて、肩肘付いてポチポチするだけで各種設定が行えるのは楽です。僕はNagiosの方が運用経験は長いのですが、正直どちらを使ってもいいかなと思います。現在ではrpm/debパッケージもきちんと整備されていますし導入コストの差は僕は感じません。MySQLの知識がある方にはZabbixをオススメします。
Muninプラグイン
(Python製)
リソース監視ツール MuninのRedis用プラグインです。僕も昔に業務でRedis用のMuninプラグインは作ったことはありますが、ここではデフォルトで多くの項目を監視できる PyMunin というMuninプラグインを紹介したいと思います。導入は簡単で、pip または easy_install からインストールできます。
1 2 3 4 5 6 7 8 |
## PyMuninのインストール $ pip install PyMunin ## Muninのプラグインディレクトリ(/etc/munin/plugins)へのシンボリックリンクを貼る $ sudo ln -s /path/to/pymunin-redisstat.py /etc/munin/plugins ## munin-nodeを再起動 $ sudo service munin-node restart Stopping Munin Node agents: [ OK ] Starting Munin Node: [ OK ] |
あとはブラウザからMuninのWebインタフェースにアクセスして以下のように正常にグラフが出力されているか確認します。
(クリックで拡大)
上の画像では一部の監視項目しか見えていませんが、デフォルトでグラフ出力される監視項目を以下に挙げます。充実していますね。
- Ping Latency (secs)
- Active Client Connections
- Client Connections per Sec
- Commands Processed per Sec
- Memory Usage (bytes)
- Memory Fragmentation Ratio
- CPU Utilization
- Hits/Misses per Sec
- Expired Keys per Sec
- Evicted Keys per Sec
- Subscriptions
- RDB Pending Changes
- RDB Dump Duration (sec)
PyMuninはRedis以外にもMySQLやmemcached, Nginxなどいろいろなミドルウェアのプラグインの詰め合わせになっているのでMuninを使っている人は導入をオススメします。
Cactiプラグイン
(PHP製)
こちらもリソース監視ツール CactiのRedis用テンプレート。
(クリックで拡大)
すみません、Cactiの環境が手元にないのでこれだけ試せていません(いいわけ)。Cacti自体の導入が済んでいればプラグインの追加は簡単です。機能面ではこれまで紹介してきたツールと大差はありません。また、このプラグインはSSH経由でデータを取得するタイプなので、プロダクション環境のネットワークポリシー的には利用不可な場合もあるでしょう。
以上、簡単にですがRedis関連の監視/解析系ツールをまとめてみました。数百ノードの規模を分散監視する場合はNagiosやZabbixのような統合監視ツールを使うと安心ですが、じっくり腰を据えてシステム構築する必要があるので多少時間がかかります。小中規模であれば好きなプロダクトを使うといいんじゃないでしょうか。
参考:
Redis DB – Google グループ
Redis Masterclass – Part 2, Monitoring
ぜんぜん関係ないけど、NYUがDeep Learningによる画像認識デモを公開してた。これはすごい。
Image Classifier Demo
130万枚の画像からDeep Learningで学習した特徴量を使ってるらしい。僕が学生時代はニューラルネットって下火みたいな感じになってたけど、Deep Learningの登場でまた盛り上がってきた。僕も勉強せねば。
2 Thoughts