oranie's blog

旧:iをgに変えると・・・なんだっけ・・・

ここ最近のCassandra運用の色々まとめメモ

まあそんな内容でも誰かの役に立つかもしれないのでメモを書いておく。体系だったまとめでも無いのでそんなレベルで。

運用とか

http://ameblo.jp/principia-ca/entry-11514557323.html
こんなブログを書いたので、そっちを見てみて下さい(ステマ

テストスクリプトとか。

https://github.com/oranie/oranie/blob/master/cassandra/cassandra_test_data.pl
こんな感じで、僕の場合perlでCassandra::Lite使うと楽だった。

Cassandra::Liteメモ

# Insert it.
$c->put($columnFamily, $key, {title => 'testing title', body => '...'});

And get data:

# Get a column
my $scalarValue = $c->get($columnFamily, $key, 'title');

# Get all columns
my $hashRef = $c->get($columnFamily, $key);

簡単ですね(ニッコリ

データの持ち方とか

かなり初歩な話。どっちかというと同僚の
Cassandraメモその1(インストール、データモデル、データ操作について)
を見たほうがちゃんとしているので良いですよ。


Cassandraはkeyspace -> column family -> row -> column:value
というデータの持ち方。
良くある例えでMySQLでいうと
key space -> database
column family -> table
row -> レコード
column -> カラム
value -> カラムに格納される値
という感じ。
今はcolumn family作ろうとするとCQL(Cassandra Query Language)では普通にCREATE TABLE、ALTER TABLE文なので、もうTABLEと言って良い感じ。datastaxさんの
http://www.datastax.com/documentation/cassandra/1.2/index.html#cassandra/cql_reference/cql_storage_options_c.html
この辺のドキュメント読むと結構色々とスキーマ定義出来るのが分かりますね。

すげー乱暴に言うとCssandraはkey valueを一つのrowに一杯入れて管理出来る。で、何が嬉しいかとかどういう使い方が良いかとかで言うと、Twitterのユーザー毎のつぶやきを管理してみようと思った場合にユーザーoranieで例にとってみようと思うと
※適当な例なので、この構造が良いか悪いかは一旦置いておいて下さい。
row key:oranie1でrowを作成して、その中にkey valueとして

user:oranie date:20130710120001 text:おなか痛い

を入れておき、次にrow keyでoranie2で

user:oranie date:20130710120010 text:('A`)ヴァーヴァー

みたいなデータをどんどんぶち込んでいけたり出来るね。もっと言うと

user:oranie date:20130710120001 text1:おなか痛い text2:腹減った text3:酒飲みたい text4:明日休もう ..........

みたいな感じで数千万カラムとかぶっこんでも一つのrow keyを指定してモリッと取ってこれる。でも一つのrowに数千万カラムとか入れるのはやめた方が良いですね。理由としてはまあ色々思いつくけど、一番大きいのはCassandraはrow key単位で各ノードに分散して置くので、一つのrowがデカイとそこが局所的な負荷の原因になるから。可能な限りrow keyが散らばるデータモデリングをしましょう。もっとちゃんとしたデータモデリングについてはebayの人が発表した

とかdatastaxのPatrick McFadin さんの資料
とかこの人の資料はデータモデリングについての発表が多いので
http://www.slideshare.net/patrickmcfadin
辺りを読んでおくと幸せになれるんじゃないでしょうか。

Verアップについて

メジャーVerアップは結構難しい。マイナーVerアップでも1.1.7以前 -> 1.1.8以降についてはメジャーアップデート相当レベルなので気をつけて。stream stageで使用するプロトコル仕様に変更が入っているらしい。
1.1.x -> 1.2.xはメジャーアップデート。で、単純にバイナリだけ変わっていれば良いという訳ではなくて、データをファイルに書きだしたSSTableを一度アップデートしたVer仕様にする処理が必要な為、nodetool upgradesstableコマンドを実行しないといけない。で、これはデータ量に比例して処理時間掛かる。で、全てのノードが完了するまでのリスクとして、さっき書いたstream処理という括りの処理はエラーになる。具体的には各ノード間でデータのやりとりをする処理。ノードの追加、削除、repairとか。
僕のいるチームはこの辺を@yukimさんに色々教えて貰ったのでこれから挑戦する・・・予定。
マイナーVerアップは普通にrpmとか使っていればrpmをアップデートするだけでOKなはず。

クラスタの分割について

一旦メンテナンスによる停止時間が作れるなら簡単かも。但し、これもデータ量によるね。
以下はまたも@yukimさんに教えて貰ったまんまの正当なルート。
1. 新規にクラスタを新しい名前で構築
2. 新クラスタにコピーするキースペースやカラムファミリのスキーマ作成
3. スナップショットをバルクロード

3. には2つ方法がある。

a. bin/sstableloader コマンド
b. JMX経由(org.apache.cassandra.db:type=StorageService の bulkLoad)

以下@yukimさんの解説をそのまま引用させて頂きます><

a. はCassandraノード外からデータを流し込む場合に利用し、b. はすでにCassandraノードと同じマシンにおいてあるデータを流し込む場合に利用します。
b. の場合でも、もし流し込むデータがJMXを実行したノードのトークン範囲外のデータであれば、そのデータが属するべきトークン範囲を持つノードにデータを転送します。

* sstableloader
bin/sstableloader -d (cassandraクラスタ内のノードのアドレス) <SSTableを格納したディレクトリ>

-d で指定したノードにまずアクセスして、クラスタの情報(トークンとか)を取得します。

* JMX bulkLoad
jconsole とかで実行します。文字列を引数にとりますが、そこにSSTableを格納したディレクトリを指定します。

注意点としては、両方ともSSTableを格納したディレクトリを指定しますが、Cassandraのデータディレクトリと同じように、'キースペース名/カラムファミリ名/' というディレクトリ構成にしておかなければ行けません。

という形でスナップショットをmysqldumpで取得したdumpファイルとして使う感じですな。ちなみに、単純にスナップショットを新しいクラスタにコピーだとクラスタ名が同一じゃないと起動出来無いので注意。ただ、分割という目的の場合同一クラスタ名のクラスタが2個存在するとかは無いよね。
あと、一時的な用途だからって単純に既存クラスタのコピークラスタを作ろうとした時に、スナップショットをコピーしただけでは駄目でsystem領域にあるNodeInfoとLocationInfoを削除してからスナップショットを起動しないと元のクラスタに入ろうとするので注意。一回テスト環境でやらかした・・・。あの時は焦った。ここはcassandra.yamlのseedとか変えていても上記の箇所で元のクラスタの構成データ持っているので、configでちゃんとIP変えているから大丈夫だろーとかやるとハマる。

他いろいろ

multithread compactionはまだ安定していないらしいのでやっぱりOFFが良いらしい。
simple strategyの時はノードの障害影響範囲が見えやすいけど、vnode使うとパッと見では人類では把握しきれないのでバックアップの管理とか色々考えるとまだsimple strategyが良いかも。vnode使ったほうが分散がsimple strategyより偏り減るらしいのでやってみないと分からんが。
とりあえずdatastaxのドキュメント読むのが今は一番の教科書。
http://www.datastax.com/documentation/cassandra/1.2/index.html


こんな感じで自分でなんかやっていると言うよりは@yukimさんに教えて貰ってばっかりなのでアレな感じだけど、Cassandra良いですよ。初めは慣れていなかったのと途中で一回地雷Ver(1.1.3)を踏んだのでヽ(`Д´#)ノ ムキー!!ってなったけど、今は自分で運用している環境では落ち着いてます。むしろ今までは周りの人にCassandra大変だーとか言っていたので少しでも悪名を取り除き仲魔を増やしたい。
ただ、Cassandraは良いけど単純に「マルチマスタひゃっほう!(^ω^)」「分散データストアだから今のMySQLの性能問題なくなるでしょ(^ω^)」とかな気持ちで乗り換えると想定した事態にならないと思う。データモデリング的に合っているとか、TBは超えるデータを扱うかとかが判断材料だとは思う。GBレベルのデータなら今はMySQLとかのRDBMSでFusion-IO載せたほうが楽なんじゃないかな。マルチマスタだけど一貫性レベルでQUORUMとか使っていたり+レプリカセットの数との関係でノードダウンした時に書き込み・読み込み出来ないとかの事態はあるので。性能に関しても少ないリクエストの中でレイテンシを今より下げたい!という方向には向かないんじゃないかなぁ。ノード数増やせばある程度は下がるとは思うけど。向いているのは大量のリクエスト時にレイテンシの悪化を緩やかにしたいとかの方向な気がする。ただ環境と使い方次第なので性能関係の話はまあこんな適当な感じなのであてにしないで自分で試してみて下さい。

最後に@yukimさんが素敵なスライド出しているので紹介。コードを書く以外にも色んなことでプロジェクトに貢献出来るんだという良い話。