2010年11月7日日曜日
Cassandraのインストール、設定からRubyによる操作までのメモ
◆ 目的
Cassandra(ver 0.6)をインストールし、最低限動くまでの設定をする。
そしてThrift APIとしてRubyを使いCassandraを操作できるようにする。
◆ Cassandraのデータモデルの予備知識
言葉の定義だけは覚えておく。
SQLと比較しながら見るとイメージしやすいだろう。
(SQLでの挿入文)
INSERT INTO Keyspace.ColumnFamily (age) VALUES("30") WHERE id="user";
(Cassandraでの挿入文)
set Keyspace1.ColumnFamily_Standard1["user"]["age"] = "30"
\ \ \ \ \
\ \ \ key \ name \ value
\ keySpace \ \
\ ColumnFamily \ column
● キースペース(KeySpace) ※SQLでいうところのデータベース
複数のカラムファミリを持つ。
設定ファイルに指定。
● カラムファミリ(ColumnFamily) ※SQLでいうところのテーブル
カラムまたはスーパーカラムの集合。
設定ファイルに指定。
● カラム(Column)
Cassandraのデータ最小単位。
nameとvalueから成る。
設定は動的。
● ロウ(Row)
キーに紐づいて取得できるカラムの集合。
一つのキーに対してカラムは一つとは限らない。
上の例でいうと、userというキーに対して、
age以外に、genderなどのカラムを持っていてもよい。
use名をキーにして年齢と性別という2つのカラムを取得できる。
このカラム群がロウである。
set Keyspace1.ColumnFamily_Standard1["user"]["age"] = "30"
["gender"] = "man"
\
\ row(複数のcolumn)
カラムファミリはロウごとにソートされており、
アクセスされる場合もこのロウが基本単位となる。
◆ ダウンロード
# cd /usr/local/src
# wget http://www.meisei-u.ac.jp/mirror/apache/dist/cassandra/0.6.6/apache-cassandra-$VERSION-bin.tar.gz
# tar zxvf apache-cassandra-$VERSION.tar.gz
◆ 必要なディレクトリの作成
# cd apache-cassandra-$VERSION
# mkdir -p /var/log/cassandra
# mkdir -p /var/lib/cassandra
◆ 初期設定
【環境の設定】
# cp bin/cassandra.in.sh bin/cassandra.in.sh.default
# vi bin/cassandra.in.sh
JAVA_HOME=/usr/bin
JVM_OPTS=" \
-Xms512M \
-Xmx512M \
-Dcom.sun.management.jmxremote.port=8080 \
※
-Xms : 初期ヒープサイズ
-Xmx : 最大ヒープサイズ
Xms ≦ Xmx とすること
JMXでの接続ポート : 8080
【ログの保存先の設定】
# cp conf/log4j.properties conf/log4j.properties.default
# vi conf/log4j.properties
システムログの保存先の設定
log4j.appender.R.File=/var/log/cassandra/system.log
【起動時の各種設定】
# cp conf/storage-conf.xml conf/storage-conf.xml.default
# vi conf/storage-conf.xml
ThriftでのRPCポートの設定
<ThriftPort>9160</ThriftPort>
複数Cassandrraノードのコミュニケーションポートの設定
<StoragePort>7000</StoragePort>
コミットログディレクトリの保存先の設定
<CommitLogDirectory>/var/lib/cassandra/commitlog</CommitLogDirectory>
データディレクトリの保存先の設定
<DataFileDirectories>
<DataFileDirectory>/var/lib/cassandra/data</DataFileDirectory>
</DataFileDirectories>
ノードの設定
さしあたり、単一ノードで動作させる
<Seeds>
<Seed>127.0.0.1</Seed>
</Seeds>
キースペース/カラムファミリの設定
(設定前の備忘録)
・ColumnType属性
Standart : カラムファミリ内にカラムが含まれる
Super : カラムファミリ内にスーパーカラムが含まれる
・CompareWith属性
スーパーカラムのソートオプション
・CompareSubcolumnsWith
スーパーカラム内のカラムのソートオプション
<Keyspaces>
<Keyspace Name="Keyspace1">
<ColumnFamily Name="ColumnFamily_Standard1"
ColumnType="Standart"
CompareWith="BytesType"
KeysCached="1000"
RowsCached="100"
RowCacheSavePeriodInSeconds="0"
KeyCacheSavePeriodInSeconds="3600"/>
※ColumnTypeの指定をしなければ、ディフォルトStandard
<ColumnFamily Name="ColumnFamily_Super1"
ColumnType="Super"
CompareWith="BytesType"
CompareSubcolumnsWith="BytesType" />
</Keyspace>
</Keyspaces>
◆ 起動
# bin/cassandra -f
-f: start in foreground
◆ コマンドラインによるデータの操作
# bin/cassandra-cli --host localhost
> help
ここでコマンドは確認できる。
また、コマンドはタブ補完が可能である。
> show keyspaces
> set Keyspace1.ColumnFamily_Standard1["user"]["first"] = "John"
> set Keyspace1.ColumnFamily_Standard1["user"]["last"] = "Smith"
> set Keyspace1.ColumnFamily_Standard1["user"]["age"] = "30"
SQL的に書けばこうなる。
INSERT INTO Keyspace1.ColumnFamily_Standard1 (age) VALUES("30") WHERE id="user";
> get Keyspace1.ColumnFamily_Standard1["user"]
> del Keyspace1.ColumnFamily_Standard1["user"]
> quit
◆ Thrift APIによる操作
今回はRubyを利用する。
1) RubyでCassandraを操作するライブラリをRubygemsからインストールする
# gem install cassandra
※ Rubygemsがなければ先にインストールしておくこと
# yum install rubygems
2) RubyからCassandraを操作する
# vi file.rb
require 'rubygems'
require 'cassandra'
# 接続する
client = Cassandra.new("Keyspace1", "127.0.0.1:9160")
# キースペースを表示する
client.keyspaces
# 各種カラムへデータを追加する
client.insert(:ColumnFamily_Standard1, "key1", { "first" => "John" } )
client.insert(:ColumnFamily_Standard1, "key1", { "last" => "Smith" } )
client.insert(:ColumnFamily_Standard1, "key1", { "age" => "42" } )
# スーパーカラムを持っている場合は下のようにする
client.insert(:ColumnFamily_Super1, "key1", {"key2" => {"first" => "John"}})
client.insert(:ColumnFamily_Super1, "key1", {"key2" => {"last" => "Smith"}})
client.insert(:ColumnFamily_Super1, "key1", {"key2" => {"age" => "42"}})
# 各種カラムへ一度にデータを追加するには下のようにする
client.insert(:ColumnFamily_Standard1, "key1", { "first" => "John", "last" => "Smith", "age" => "42" } )
# 下記でも同様だが、ブロックを使うとアトミックに処理できる
# また、ThriftのAPIを一行ずつコールしないので効率的である
client.batch do
client.insert(:ColumnFamily_Standard1, "key1", { "first" => "John" } )
client.insert(:ColumnFamily_Standard1, "key1", { "last" => "Smith" } )
client.insert(:ColumnFamily_Standard1, "key1", { "age" => "42" } )
end
# ロウを取得する
client.get(:ColumnFamily_Standard1, "key1")
# スーパーカラムを持っている場合は下のようにする
client.get(:ColumnFamily_Super1, "key1", "key2")
# 特定のカラムの値を取得する
client.get_columns(:ColumnFamily_Standard1, "key1", ["first"])
# キーとロウのペア群を取得する
# キーの一覧を出したい場合にも利用できる
client.get_range(:ColumnFamily_Standard1).each do |obj|
obj.columns.each do |column|
end
end
# また下記のようにキーの始まりと終りを指定し、範囲を絞ってのデータ取得も可能である
# その他オプションとして":count"、":consistency"も指定ができる
client.get_range(:ColumnFamily_Standard1, \
:start => "カラムの始まり", :finish => "カラムの終わり")
# スーパーカラムを持っている場合の範囲を絞ってのデータ取得は下記である
# スーパーカラムを特定するキー"key1"は固定していることに注意すること
# ここでは、カラムを特定するキーの範囲を指定している
client.get(:ColumnFamily_Standard1, "key1", \
:start => "キーの始まり", :finish => "キーの終わり")
# 指定したキーのカラムを削除する
client.remove(:ColumnFamily_Standard1, "key1")
client.remove(:ColumnFamily_Super1, "key1", "key2")
# カラムの存在を調べる(存在しなければnilが返る)
client.exists?(:ColumnFamily_Standard1, "key1", "age")
client.exists?(:ColumnFamily_Standard1, "key1", "hoge")
# カラムの数を数える
client.count_columns(:ColumnFamily_Standard1, "key1")
Cassandraの基礎が理解できただろうか。
次はログ検索を高速に行うための、独自アプリケーションを作成してみる。