はじめに
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 を使うと良さげ。
クラスタ全体のリソース状況。
クラスタ内の各ノードのステータス。
最後に
- まだまだ続くよー