前回でCassandraへのアクセスするコードの基本をおさえました。今回解説するのは以下の2点です。
- CassandraのAPIの全体像
- Cassandraにデータを投入するコードの詳細
3つの分類からAPIの全体像をおさえる
第1回でもご紹介しましたが、CassandraのクライアントAPIはThriftによって自動生成されます。APIは非常にシンプルなものが幾つかあるだけで、覚えるのもさほど難しくはありません。本連載ではその中からよく使うものに特化してご紹介していきます。
以下にCassandraのAPIを、データ挿入系・データ検索系・認証/管理系の3つに分類してまとめてみました。まずはこれらにひと通り目を通してみてください。
データ挿入/更新/削除のAPI
データ挿入、更新、削除のAPIは以下の表のとおりです。現実的によく使う中心的なAPIはbatch_mutate、removeの2つです。この連載でも幾度と登場することになるので、まずはこれらをおさえておいてください。
表1 データ挿入、更新、削除のAPI
メソッド名 | 説明 |
insert | カラムファミリかスーパーカラム内に1件カラムを挿入する |
batch_insert | 同一キー内のカラムやスーパーカラムを一括挿入する[1] |
batch_mutate | バッチ的に複数のカラムまたはスーパーカラムを更新する |
remove | 特定行のデータまたはカラムファミリまたはスーパーカラムを指定して削除する |
データ検索系
データ検索系の中心となるのはget_slice、get_range_slicesの2つです。特定のキーまたはキーのグループがわかっている場合にはmultiget_sliceを使うといいでしょう。検索結果が無い場合の挙動がそれぞれのAPIで多少違うので、あわせて付記しておきました。
表2 データ検索系のAPI
メソッド名 | 説明 | 検索結果が無い場合の挙動 |
get | 特定キーからカラムまたはスーパーカラム1つを取り出す | NotFoundExceptionが発生する |
get_slice | スライスされたカラムまたはスーパーカラムの集合を返す | 空のListを返す |
multiget | 複数キーに対して並列に複数getをこなす | 値のカラムまたはスーパーカラムが空のMapを返す[2] |
multiget_slice | 複数キーに対して複数のget_sliceを並列にこなす | 値のカラムまたはスーパーカラムが空のMapを返す |
get_count | カラムファミリまたはスーパーカラム内のカラム数を数える | 0を返す |
get_range_slice | キーレンジでカラムのサブセットを返す | 空の配列を返す[3] |
get_range_slices | キーレンジでカラムのサブセットを返す | 空の配列を返す |
認証/管理系API
認証管理系のAPIで重要なのは、認証を行うloginです。loginでどのような挙動を行うかは設定により変更可能です。
運用・管理については、じつは別途nodetool、nodeprobeといったツールが準備されているので、APIよりそちらを利用するのが一般的です。しかし、プログラム経由で運用・管理を行いときのために知っておくとよいでしょう。
表3 認証/管理系API
メソッド名 | 説明 |
login | キースペースごとに認証する |
get_string_property | ノードやクラスタ情報をキー指定で取り出す[4] |
get_string_list_property | ノードやクラスタ情報を取り出す[5] |
describe_keyspaces | キースペースを取り出す |
describe_cluster_name | クラスタ名を取得する |
describe_version | Thrift APIのバージョン名を取得する |
describe_ring | トークンのレンジとホストアドレスのリングを表示する |
describe_keyspace | キースペース内のカラムファミリ名とその属性のMapを取得する |
describe_splits | Hadoopの並列処理クエリ用の実験的なAPI[6] |
カラムを1つ挿入する
では、Cassandraへの操作を書いていきましょう。まずはデータがないと何もならないので、データを入れてみます。前回もデータ挿入のサンプルをご紹介しましたが、Cassandraへデータを入れるには大きく分けて2つの方法があります。
- insertでカラムを1つづつ入れていく
- batch_mutateでバッチ的に一気にデータを投入する
前出の表1にはbatch_insertというAPIも記載しましたが、今後廃止予定になっているので本連載では割愛します。ひとまず、前回の振り返りでinsertでカラムを挿入するところからはじめてみましょう。
カラムを1つ挿入するにはinsertを使います。insertは以下の引数をとります。
ColumnPathでデータの格納場所を、ConsistencyLevelで一貫性レベルを指定
前回の最後にご紹介したコードの抜粋を使っておさらいしておくと、実際には以下のような形で使います。
この中で、ColumnPathとConsistencyLevelの2つはまだあまり馴染みの無いと思います。くわしく見ていきましょう。
ColumnPath
ColumnPathはカラムファミリとカラム名を特定するためのクラスで、その名のとおりデータをどこに格納すればよいかを明示します。ディレクトリ構造におけるパスのような扱いと思ってもらえれば差し支えありません。そのため以下の指定を行う必要があります。
表4 ColumnPathで指定する項目
カラムファミリ名 |
カラム名 |
スーパーカラム名(スーパーカラムを使っている場合) |
ConsistencyLevel
Cassandraでは全ての操作で、その操作に対する一貫性レベルをクライアントコードから与える形式をとっています。全ての操作の引数にConsistencyLevelのenumがついてくるのはそのためです。ConsistencyLevelは書き込み時と読み込み時で表5のような意味を持っています。
表5 ConsistencyLevelの一覧
ConsistencyLevel | 読み込み時 | 書き込み時 |
ZERO | 使用不可 | 何も保障しない書き込み。非同期に実行される |
ONE | もっとも最初に読めた1ノードのデータを返す(※7) | クライアントに返すまでの間に1ノードに書き込まれることを保障する |
QUORUM | 全ノードの内、レプリケーション数 / 2+1からデータが読めたら返す。返すデータは最新のタイムスタンプのものを返す | クライアントに返すまでの間に(レプリケーション数 / 2+1)のノードに書き込まれることを保障する |
DCQUORUM | 0.6.1ではALLと同等(※8) | 0.6.1ではALLと同等 |
DCQUORUMSYNC | 0.6.1ではALLと同等 | 0.6.1ではALLと同等 |
ALL | 全ノードから読めた場合、データを返す(※9) | クライアントに返すまでの間にレプリケーション数だけ書き込まれる事を保障する |
ANY | 使用不可 | 1度どこかのタイミングで書き込まれる事を保障する |
注意すべき点は、これらの一貫性はノード数全体ではなく、storage-conf.xmlで指定したレプリケーション数によって決まる点です。具体的には<ReplicationFactor>の設定で、キースペースごとに指定します。
RDBMSのようなACIDでの強度な一貫性と異なり、CassandraはEventual Consistency(一貫性のある状態にいつか到達する)という思想に基づき設計されています。つまり、一貫性を緩める代わりに応答速度を向上させるという狙いがあります。ConsistencyLevelにバリエーションがあるのもそのためです。
スーパーカラム内の1つのカラムにデータを入れる
ではサンプルコードに戻って、スーパーカラム内の1つのカラムにデータを入れてみましょう。
スーパーカラム内のカラムにデータを入れる方法は、カラムのときとほとんど変わりません。違うのはColumnPathでどのスーパーカラムのどのカラムかを指定するようにしている点だけです。スーパーカラムとカラムは、以下のようにして指定します。
- columnPath.setSuper_column() → スーパーカラム名を指定
- columnPath.setColumn() → カラム名を指定
カラムを複数まとめて追加する
次は複数カラムをまとめて追加してみましょう。複数カラムをまとめて追加するにはbatch_mutateを使います。batch_mutateは以下の引数をとります。
batch_mutateでポイントとなるのは、真ん中の引数のmutation_mapです。ここにカラムファミリのキーとカラムファミリを指定して、Mutationというオブジェクトを保持する構造になっています。図2を見てください。
ここで出てくるMutationとは、挿入と削除を表現するためのオブジェクトのことです。Mutationは、カラムまたはスーパーカラムを保持する役目を持つColumnOrSuperColumnと、削除を表現するDeletionを持ちます。オブジェクト構造は図のMutationのようになっています。
では、3つのカラムをアップデートするコードをみてみましょう。以下は一部抜粋なので、全体はサンプルファイルのダウンロードからご確認ください。
この例ではhoge、foo、barというカラム3つをbatch_mutateを使って挿入しています。実際にカラムを追加している部分は、Mutationを作成しているところです。
スーパーカラム内のカラムを複数まとめて追加する
では最後に、スーパーカラム内のカラムを複数まとめて追加してみましょう。
やり方はカラムを複数追加するときとあまり変わりありません。唯一違うのは、SuperColumnを作成して、Columnを複数追加するところだけです。
注意していただきたいのは、SuperColumnは名前が必須になる点です。SuperColumn#setName()でスーパーカラム名を忘れず設定しましょう。ここでは"shot_profile"という名前をつけました。
今回はCassandraのデータの挿入に着目して、紹介しました。
実際に使うときは、Cassandra用のユーティリティを自前で作るなり、既存の高レベルなクライアントフレームワークなりを使うことが多くなります。ただ、プリミティブなレベルでどのようなコードになるかをイメージできるようにしておくと効率的にCassandraにアクセスできるようになるので、ひと通り知っておくといいでしょう。
なお、今回作成したサンプルプログラム全体は、以下からダウンロード可能です。
次回はデータの更新と削除について紹介します。お楽しみに。