ようへいの日々精進XP

よかろうもん

Cassandra の運用と監視についてメモ

はじめに

  • 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"

上記の seedsseed 役のホストの 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 

Addressxxx.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 を使うと良さげ。

f:id:inokara:20140108014344p:plain

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

f:id:inokara:20140108014451p:plain

クラスタ内の各ノードのステータス。


最後に

  • まだまだ続くよー