9月半ばくらいから仕事でCassandraに触れている。現場でCassandraの機嫌を取ったり、同僚とオライリー本を輪読したり、手元でいじったりしているうちにCassandraをある程度習得することができた(つもり)。なのでメモを残しておく。今日は第一弾としてCassandraの特徴、インストール、データモデル、データ操作についてまとめる。なお、ここで言及しているCassandraのバージョンは1.1.5。



(1) Cassandraの特徴

まずは特徴を列挙する。

  • 列指向分散DB
  • 4次元または5次元の構造
    • キースペース、カラムファミリ、ロウ、(スーパーカラム)、カラムの順に入れ子構造となる。
    • カラムは値とタイムスタンプをもつ。タイムスタンプはカラム挿入時に自動で付与される。
    • カラムは挿入時にTTLを設定することにより時限削除可能。
  • データ操作は挿入、削除、参照のみ。
  • データの更新は挿入による上書き。
  • データの削除は内部的には論理削除として扱われる。つまりデータ容量は減らない。
  • 参照はロウのキーまたはロウのキー+カラム名による検索のみ。
    • ただしインデックスを張れば特定のカラム値での検索が可能。
  • クラスタはリング型のトポロジとなる。
  • シングルポイントレス。
  • CAP定理でいうとConsistencyを犠牲にしている。
    • データアクセス時に整合性レベルを採択可能であるが、高い整合性を欲するとレスポンス速度は落ちる
(2) インストール

公式サイトからtar.gzを入手して展開するだけでインストールはできる。Cassandraのサポートを行っているDATASTAX社のリポジトリにはRPMやDEBもあるので、パッケージによるインストールも可能。なお、CassandraはJava製のため、Javaのインストールも必須となる。DATASTAX社によるとjdkの推奨バージョンは1.6系(1.7系は非推奨とのこと)。
ここでは、Cassandraをtar.gzから/usr/local/cassandraにインストールする手段について記す。展開するだけだけどw

1
2
3
4
cd /usr/local
wget http://ftp.jaist.ac.jp/pub/apache/cassandra/1.1.5/apache-cassandra-1.1.5-bin.tar.gz
tar xvfz apache-cassandra-1.1.5-bin.tar.gz
ln -s /usr/local/apache-cassandra-1.1.5 cassandra

(3) ファイル構成

インストールされるファイル一式(抜粋)について記す。
  • /usr/local/cassandra配下
    • /usr/local/cassandra/conf
      • コンフィグファイル格納ディレクトリ。
    • /usr/local/cassandra/conf/cassandra-env.sh
      • Cassandra起動時に読み込まれるJVMの起動オプションなどの定義がなされている。JVMのオプションをコンフィグレーションする場合はこのファイルをいじる。
    • /usr/local/cassandra/conf/cassandra-topology.properties
      • スニッチがPropertyFileSnitchのときに使用される設定ファイル(スニッチはCassandraの各ノードの場所を推測/決定するための仕組みで、クラスタ構成を組んだときに重要な概念になってくる。スニッチについては後の記事で記載する)。
    • /usr/local/cassandra/conf/cassandra-rackdc.properties
      • スニッチがGossipingPropertyFileSnitchのときに使用される設定ファイル(スニッチについては後の記事で記載する)。
    • /usr/local/cassandra/conf/cassandra.yaml
      • Cassandraのメイン設定ファイル。
    • /usr/local/cassandra/conf /log4j-server.properties
      • Cassandraのログ設定ファイル。ログレベルなどが調整可能。
    • /usr/local/cassandra/conf /log4j-tools.properties
      • Cassandraの各種管理スクリプト(nodetoolやsstableloaderなど)のログ設定ファイル。
    • /usr/local/cassandra/bin
      • 起動スクリプトや各種管理スクリプトの格納ディレクトリ
    • /usr/local/cassandra/bin/cassandra
      • Cassandra起動スクリプト。後述するが、このスクリプトの引数にstartを与えることによってCassandraを起動する。
    • /usr/local/cassandra/bin/cassandra-cli
      • コマンドラインツール。Cassandra起動中にこのスクリプトを実行することによって、Cassandraのコマンドラインインターフェイスに入ることができる。
    • /usr/local/cassandra/bin/cassandra.in.sh
      • 起動時にインクルードされるスクリプト。Cassandraのホームディレクトリや、コンフィグファイル格納ディレクトリの場所が記載されている。
    • /usr/local/cassandra/bin/nodetool
      • クラスタの管理を行うためのスクリプト。クラスタ構成時に多用する。
  • /var/lib配下
    • /var/lib/cassandra
      • このディレクトリを含め、この配下のディレクトリは自分で掘る。Cassandra設定ファイル(cassandra.yaml)のデフォルトではこの下にデータ/コミットログを吐くようになっているため。
    • /var/lib/cassandra/commitlog
      • コミットログ出力用ディレクトリ
    • /var/lib/cassandra/saved_cache
      • キーキャッシュやロウキャッシュの情報が格納されるディレクトリ
    • /var/lib/cassandra/data
      • データファイル格納用ディレクトリ
  • /var/log配下
    • /var/log/cassandra
      • このディレクトリは自分で掘る。Cassandra設定ファイル(cassandra.yaml)のデフォルトではこの下にログを吐くようになっているため。
    • /var/log/cassandra/system.log
      • Cassandraのログ。Cassandra稼働中のイベントが記録される。
(3) Cassandra起動

/usr/local/cassandra/bin/cassandra startで起動できる。このままでも起動できるが、起動時に読み込むファイルやコンフィグディレクトリなどを環境変数で指定してあげると良い。bin/cassandraスクリプトを読むとわかるが、CASSANDRA_INCLUDE環境変数でcassandra.in.shを、CASSANDRA_CONF環境変数でコンフィグの場所を、JAVA_HOME環境変数でJavaの場所を探している。さらに読み込んだcassandra.in.shからはCASSANDRA_HOME環境変数が参照され、CASSANDRA_HOME/lib配下のjarをクラスパスに追加している。なので次のようにしてあげると良いだろう。

1
2
3
4
5
6
7
8
# Javaのパスは例
export JAVA_HOME=/opt/java
# Cassandraのパスは/usr/local配下にインストールした前提。
export CASSANDRA_HOME=/usr/local/cassandra/
export CASSANDRA_INCLUDE=/usr/local/cassandra/bin/cassandra.in.sh
export CASSANDRA_CONF=/usr/local/cassandra/conf
cd /usr/local/cassandra/bin
./cassandra start

(4) Cassandraへの接続

/usr/local/cassandra/bin/cassandra-cliでCassandraのコマンドラインインターフェイスに接続できる。



(5) データ構造

Cassandaraのデータ構造は、キースペース、カラムファミリ、ロウ、カラムの4階層構造となる。またはキースペース、カラムファミリ、ロウ、スーパーカラム、カラムの5階層となる。

まず、スーパーカラムをもたないときのデータ構造のイメージを示す。

スーパーカラムがあるときのイメージは次のようになる。

キースペースはRDBでいうところのスキーマに該当する。

カラムファミリはRDBでいうとテーブルで、カラムファミリの配下に複数のロウがある。なお、カラムファミリを作成するときに、そのカラムファミリがスーパーカラムをもつかどうかをオプションで指定する。デフォルトではスーパーカラムはもたない。

ロウは一意なキーをもち、カラムの集合を扱う。RDBでいうとレコードのようなものである。RDBと異なる点は、あるロウがカラム(例:name, email, address)を持っているからといって、別のロウも同じカラムをもっていなければならないということはない(たびたびRDBを例に出しているが、RDBのレコード/カラムの概念とはまったく別)。カラムファミリがスーパーカラムを持つときは、ロウの配下に一段スーパーカラムが挟まり、その下に複数のカラムが存在するようになる。ロウは、ロウキーのバイト文字列順でソートして格納される。

カラムは値とタイムスタンプをもつ。タイムスタンプはカラム挿入時に自動付与される。ロウがソートされて格納されるように、カラムもソートされて格納される。ただし、カラムはカラムファミリ作成時のcomparatorオプション(カラム名のソートと、カラム名の入力バリデーションに影響)の設定に従ってソートされる。ここで、comparatorのデフォルト値は「ByteType」であり、これはカラム名をバイト文字列順でソートすることを意味する。他にもUTF8Type(UTF-8エンコード順でソート)など種々の設定が可能。

(6) データ操作

コマンドラインインターフェイスからデータ操作を行うためのコマンドの一部をのせておく。各コマンドの詳細な書式は 、コマンドラインインターフェイスからhelp コマンド名;(例:help create keyspace)などを実行することによって確認できる。基本的には最新の公式マニュアルを参照していただくと良い。当然であるが、バージョンがあがるに従って廃止されたオプションなどもある。例えば、オライリー本(0.8系あたりを中心に書かれている)や日本語wikiでは、カラムファミリ作成時にkeys_cacheやrow_cacheといった、データキャッシュのサイズを設定できるとの記載がある。しかし現在の最新である1.1系からはこのオプションは消えてるようだ(キャッシュサイズは設定ファイルに記載し、カラムファミリ作成時オプションでは何をキャッシュするか、ロウ全部なのか?キーだけなのか?などを設定する方式に変更されているっぽい)。

キースペース作成

1
2
# oreキースペースを作成する
create kyespace ore;

キースペースに移動する

1
2
# oreキースペースに移動する。カラムファミリの作成や操作は対象のキースペースに移動してから行う。
use ore;

キースペースのオプション

キースペースは作成時にオプションを指定できる。

1
2
3
4
5
6
7
8
9
10
# 書式
CREATE KEYSPACE keyspacename WITH オプション1 AND オプション2 AND オプション3・・・;

# (例)
# レプリケーションストラテジ=SimpleStrategy
# レプリケーションファクタ=1
# で、キースペースoreを作成
create keyspace ore with placement_strategy = 'SimpleStrategy' and strategy_options={replication_factor : 1};

オプションは単純にオプション名=値で設定できるが、上記のようにjsonライクな形式で指定しないとダメなものもある。

キースペースの情報を見る

1
2
# oreキースペースの情報(オプションやそのキースペースに含まれるカラムファミリetc)を見る。
describe ore;

カラムファミリ作成

1
2
# Usersカラムファミリを作成する。
create column family Users;

カラムファミリのオプション

カラムファミリは作成時にオプションを指定できる。

1
2
3
4
5
6
7
8
9
10
11
# 書式
CREATE COLUMN FAMILY column_family_name WITH オプション1 AND オプション2 AND オプション3・・・;

# 例
# comparator(カラムのソート順とカラム名の入力バリデーション) = UTF8Type
# default_validation_class(カラム値の入力バリデーション)  = UTF8Type
# key_validation_class(ロウキーの入力バリデーション) = UTF8Type
# で、カラムファミリUsersを作成
create column family Users with comparator=UTF8Type and default_validation_class=UTF8Type and key_validation_class=UTF8Type;

これらをUTF8にしとかないと、コマンドラインインターフェイスからデータを挿入/検索したときの表示がUTF8になってくれないっぽい。

カラムファミリの情報を見る

1
describe Users;

カラムの挿入

1
2
# Usersカラムファミリのロウ(キー:key1)にカラムcol1を値val1で挿入
set Users['key1']['col1'] = 'val1';

カラムのカウント

1
2
# Usersカラムファミリのロウキーkey1に含まれるカラムの数を数える。
count Users['key1'];

検索(ロウキーでロウの検索、カラムの検索)

1
2
3
4
5
6
7
8
# ロウキーで検索(ロウ(キー:key1)を検索。ロウに含まれるカラムと値がすべて表示される。)
get Users['key1'];

# カラム名で検索(ロウ(キー:key1)のカラムcol1を検索。カラムcol1とその値が表示される)
get Users['key1']['col1'];

# Usersカラムファミリを総なめ
list Users;

削除

1
2
3
4
5
6
7
8
9
10
11
# oreキースペースを削除
drop keyspace ore;

# Usersカラムファミリを削除
drop column family Users;

# Usersカラムファミリのロウ(key1)を削除
del Users['key1'];

# カラムcol1を削除
del Users['key1']['col1'];

インデックスを張る

1
2
# Usersカラムファミリの、カラムcol1にインデックスを張る
update column family Users with column_metadata = [ { column_name: col1, validation_class: UTF8Type, index_type: KEYS} ];

インデックスを張ったカラムで検索

1
2
3
4
5
6
# カラムファミリUsersの、カラムcol1の値がval1であるものを検索する
get Users where col1 = val1;

※ インデックスを張っていないと、そもそもwhere カラム名=値での検索はできない
「No indexed columns present in index clause with operator EQ」などと言われて怒られる。
なのでwhere句を使いたいときはインデックスを張る必要がある。

時限削除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# カラムcol1の生存時間を30秒としてデータ挿入する
set Users['key1']['col1'] = 'val1' with ttl = 30;

# 30秒以内であればデータ取得可能
get Users['key1'];

=> (column=col1, value=val1, timestamp=1350411820537000, ttl=30)
Returned 1 results.
Elapsed time: 2 msec(s).

# 30秒が過ぎると削除されている
get Users['key1'];

Returned 0 results.
Elapsed time: 1 msec(s).

インクリメンタル操作

オートインクリメントのような機能もある。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# default_validation_classにCounterColumnTypeを指定してカラムファミリを作成。
create column family Users with default_validation_class=CounterColumnType and replicate_on_write=true and key_validation_class=UTF8Type;

# 3回インクリメント
incr Users['key1']['c1'];
incr Users['key1']['c1'];
incr Users['key1']['c1'];
get Users['key1']['c1'];

=> (counter=c1, value=3)
Elapsed time: 2 msec(s).

# by Nを指定することによって増分値も設定できる
incr Users['key1']['c1'] by 3;

 

今日はここまで 。

 

 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <img localsrc="" alt="">

Set your Twitter account name in your settings to use the TwitterBar Section.