はじめに
Cassandraについて運用とか監視についてググった結果等をとりあえずメモしてみる
Cassandra について
- KVS
- 分散処理に対応した NoSQL タイプのデータシステム
- データと処理がノードに分散するためにノードの追加によってデータ量と処理能力がスケール
- SPOF(単一故障点)がないアーキテクチャ
- 以下のようなデータ構造を持つ
- キースペース(
RDBMSでいうところのデータベース) - カラムファミリ(
RDBMSでいうところのテーブル) - ローキー
- カラム
- バリュー
- キースペース(
運用
クラスタ構成時の注意点
クラスタ名を適切に設定する。
cluster_name: 'Hoge Cluster'
また、seed_provider を適切に設定する。
seed_provider: # Addresses of hosts that are deemed contact points. # Cassandra nodes use this list of hosts to find each other and learn # the topology of the ring. You must change this if you are running # multiple nodes! - class_name: org.apache.cassandra.locator.SimpleSeedProvider parameters: # seeds is actually a comma-delimited list of addresses. # Ex: "<ip1>,<ip2>,<ip3>" - seeds: "xxx.xxx.xxx.xxx"
上記の seeds に seed 役のホストの IP を記載する。尚、設定に関しては基本的には ${CASSANDRA_HOME}/conf/cassandra.yml に設定する。
seed に関しては、FAQ より以下を引用。
Ring内のノードがある特定のノードをseedとして参照するように設定すると、それらのノードはseedノードに対してより頻繁にGossipメッセージを送信します(詳しくはArchitectureGossipを参照して下さい )。言い換えると、seedはGossipネットワークのハブとして機能します。Seedノードが存在することにより、リング内の各ノードは他のノードの状態変化をよりすばやく検出することができるようになります。
クラスタの確認
クラスタの状態を確認するには nodetool というコマンドを利用する。
${CASSANDRA_HOME}/bin/nodetool ring
以下のような表示が出力される。
Address DC Rack Status State Load Owns Token
111582270380829037018966764153385338143
xxx.xxx.xxx.xx1 datacenter1 rack1 Down Leaving 59.62 KB 55.37% 35655612218190568770347409340628042708
xxx.xxx.xxx.xx2 datacenter1 rack1 Up Normal 55.1 KB 32.05% 90190359617762768484976710948502111271
xxx.xxx.xxx.xx3 datacenter1 rack1 Down Normal 59.5 KB 12.57% 111582270380829037018966764153385338143
尚、nodetool は上記以外にもいくつかの機能を提供する。
クラスタからノードを取り外す(通常運用時)
ノードを能動的にクラスタから切り離す際には以下のように実行する(seed 役のノードで実行する)。
${CASSANDRA_HOME}/bin/nodetool decommission -h ${hostIP}
切り離したいノード上では以下のように実行する。
${CASSANDRA_HOME}/bin/nodetool decommission
クラスタからノードを取り外す(障害発生時)
ノードの障害によりクラスタからノードを取り外す際には以下のように removetoken オプションに token の値を指定して nodetool を実行する。
${CASSANDRA_HOME}/bin/nodetool removetoken 35655612218190568770347409340628042708
尚、ノードを取り外す際に時間がかかるので注意する。試しに EC2 上の t1.micro に構築したばかりの Cassandra ノード 3 台で構成したクラスタから一台のノードを取り外す場合に一分程度掛かった。
$ /usr/local/cassandra/bin/nodetool ring
Address DC Rack Status State Load Effective-Ownership Token
124358484364410258567278157475286688927
xxx.xxx.xxx.1 datacenter1 rack1 Up Normal 36.23 KB 84.27% 22450448083574824061559257818376644105
xxx.xxx.xxx.2 datacenter1 rack1 Up Normal 36.11 KB 55.83% 49208578228297542978444511742072488795
xxx.xxx.xxx.3 datacenter1 rack1 Up Normal 31.72 KB 59.90% 124358484364410258567278157475286688927
クラスタの状態を確認して切り離し。
$ time /usr/local/cassandra/bin/nodetool decommission -h xxx.xxx.xxx.2 real 1m3.550s user 0m0.448s sys 0m0.076s
これは切り離されるノードから稼働中のノードにデータが移動する為でクラスタ内のデータ量に応じて所要時間も長くなるので注意する。
一度切り離したノードを再度クラスタに加える場合
あまりそのようなシチュエーションは無いかもしれないけど...
以下のようにして切り離したノードの Cassandra を停止してデータディレクトリを一旦削除。
/etc/init.d/cassandra stop
rm -rf ${CASSANSRA_LIB}/data/system
あらためて Cassandra を起動する。
/etc/init.d/cassandra start
以下のように起動メッセージ内にエラーが含まれていたりするが静観。
INFO 03:08:21,753 InetAddress /xxx.xxx.xxx.1 is now UP
INFO 03:08:21,754 Node /xxx.xxx.xxx.1 state jump to normal
ERROR 03:08:22,998 Error in row mutation
org.apache.cassandra.db.UnknownColumnFamilyException: Couldn't find cfId=1006
at org.apache.cassandra.db.ColumnFamilySerializer.deserialize(ColumnFamilySerializer.java:126)
at org.apache.cassandra.db.RowMutation$RowMutationSerializer.deserialize(RowMutation.java:439)
at org.apache.cassandra.db.RowMutation$RowMutationSerializer.deserialize(RowMutation.java:447)
at org.apache.cassandra.db.RowMutation.fromBytes(RowMutation.java:395)
暫くすると seed 役のホストにて ${CASSANDRA_HOME}/bin/nodetool ring を実行すると以下のように一旦切り離したノードのステータスが Joining となりリストに表示されるようになる。
Address DC Rack Status State Load Effective-Ownership Token
157358543365745777512261476362201281463
xxx.xxx.xxx.1 datacenter1 rack1 Up Normal 85.58 KB 100.00% 49208578228297542978444511742072488795
xxx.xxx.xxx.2 datacenter1 rack1 Up Normal 85.06 KB 100.00% 124358484364410258567278157475286688927
xxx.xxx.xxx.3 datacenter1 rack1 Up Joining 43.41 KB 0.00% 157358543365745777512261476362201281463
さらに時間を置くと以下のようにクラスタ内に再登録される。
Address DC Rack Status State Load Effective-Ownership Token
157358543365745777512261476362201281463
xxx.xxx.xxx.1 datacenter1 rack1 Up Normal 170.82 KB 55.83% 49208578228297542978444511742072488795
xxx.xxx.xxx.2 datacenter1 rack1 Up Normal 120.22 KB 80.60% 124358484364410258567278157475286688927
xxx.xxx.xxx.3 datacenter1 rack1 Up Normal 36.33 KB 63.56% 157358543365745777512261476362201281463
Address が xxx.xxx.xxx.3 のノードがクラスタ内でステータスが Up となった。
監視
何を監視するか?
- ポート
- プロセス
Cassandra で利用しているポート
| 用途 | ポート番号 | 備考 |
|---|---|---|
| Thrift RPC ポート | 9160 | クライアントからの処理要求を受け付ける |
| JMX | 8080 | Cassandraノードの内部情報を取得するために接続する JMX のポート |
| Cassandra ノード間のコミュニケーションポート | 7000 |
これらをノード毎に監視の設定を行う。
プロセス
Cassandra を起動すると以下のようなプロセスが立ち上がる。(apache-cassandra-1.1.12 の場合)
java -ea -javaagent:${CASSANDRA_HOME}/bin/../lib/jamm-0.2.5.jar -XX:+UseThreadPriorities -XX:ThreadPriorityPolicy=42 -Xms297M -Xmx297M -Xmn74M -XX:+HeapDumpOnOutOfMemoryError -Xss250k -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=1 -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly -XX:+UseTLAB -Djava.net.preferIPv4Stack=true -Dcom.sun.management.jmxremote.port=7199 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Dlog4j.configuration=log4j-server.properties -Dlog4j.defaultInitOverride=true -Dcassandra-pidfile=/var/run/cassandra.pid -cp ${CASSANDRA_HOME}/bin/../conf:${CASSANDRA_HOME}/bin/../build/classes/main:${CASSANDRA_HOME}/bin/../build/classes/thrift:${CASSANDRA_HOME}/bin/../lib/antlr-3.2.jar:${CASSANDRA_HOME}/bin/../lib/apache-cassandra-1.1.12.jar:${CASSANDRA_HOME}/bin/../lib/apache-cassandra-clientutil-1.1.12.jar:${CASSANDRA_HOME}/bin/../lib/apache-cassandra-thrift-1.1.12.jar:${CASSANDRA_HOME}/bin/../lib/avro-1.4.0-fixes.jar:${CASSANDRA_HOME}/bin/../lib/avro-1.4.0-sources-fixes.jar:${CASSANDRA_HOME}/bin/../lib/commons-cli-1.1.jar:${CASSANDRA_HOME}/bin/../lib/commons-codec-1.2.jar:${CASSANDRA_HOME}/bin/../lib/commons-lang-2.4.jar:${CASSANDRA_HOME}/bin/../lib/compress-lzf-0.8.4.jar:${CASSANDRA_HOME}/bin/../lib/concurrentlinkedhashmap-lru-1.3.jar:${CASSANDRA_HOME}/bin/../lib/guava-r08.jar:${CASSANDRA_HOME}/bin/../lib/high-scale-lib-1.1.2.jar:${CASSANDRA_HOME}/bin/../lib/jackson-core-asl-1.9.2.jar:${CASSANDRA_HOME}/bin/../lib/jackson-mapper-asl-1.9.2.jar:${CASSANDRA_HOME}/bin/../lib/jamm-0.2.5.jar:${CASSANDRA_HOME}/bin/../lib/jline-0.9.94.jar:${CASSANDRA_HOME}/bin/../lib/json-simple-1.1.jar:${CASSANDRA_HOME}/bin/../lib/libthrift-0.7.0.jar:${CASSANDRA_HOME}/bin/../lib/log4j-1.2.16.jar:${CASSANDRA_HOME}/bin/../lib/metrics-core-2.0.3.jar:${CASSANDRA_HOME}/bin/../lib/servlet-api-2.5-20081211.jar:${CASSANDRA_HOME}/bin/../lib/slf4j-api-1.6.1.jar:${CASSANDRA_HOME}/bin/../lib/slf4j-log4j12-1.6.1.jar:${CASSANDRA_HOME}/bin/../lib/snakeyaml-1.6.jar:${CASSANDRA_HOME}/bin/../lib/snappy-java-1.0.4.1.jar:${CASSANDRA_HOME}/bin/../lib/snaptree-0.1.jar org.apache.cassandra.thrift.CassandraDaemon
細かいバージョン番号は利用する Cassandra バージョンによって多少の違いはあると思われるが、上記のプロセスを監視すれば良いかと。
DataStax の OpsCenter の利用
マルチノードで運用する場合には DataStax の OpsCenter を使うと良さげ。

クラスタ全体のリソース状況。

クラスタ内の各ノードのステータス。
最後に
- まだまだ続くよー