MyCassandraというモジュラー式のNoSQLを作ってます。

今まではCassandra-0.6.2をベースに開発を行っていましたが、
せっかく公開するならば、新しいバージョンでやるべきと考え、現在MyCassasndra-0.7にアップグレードを行っているところです。近いうちに公開できるよう頑張ります!

今日はMyCassandraに関するドキュメントを書いていないなぁと思い、エントリにしました。

MyCassandraとは・・

Apache CassandraBigtable likeなストレージエンジンをMySQL,BDBといったRDBMSMemcached,TT,RedisといったKVSに差し替えることが出来る分散データストアです。

要するに、

Cassandraは、Dynamo + Bigtableですが、


MyCassandraは、Dynamo + MySQL, Bigtable, etc...ですw

発端

Bigtableストレージエンジンは、差分をシーケンシャルに書きこみ、読み出し時にその差分をマージするために、書き込みは高速に出来ますが、読み出し性能は犠牲になるような設計がなされています。
これを他のデータストアにすることで、これらの性能が丸々変わるのではないかと考えて、私の修士の研究として始めました。

MyCassandraの利点

MyCassandraを利用することの利点として以下のようなものがあります。

  • データの性質(書き込み頻度が高い、読み出し頻度が高い)に応じたストレージエンジンを同一データストア内で差し替え可能
  • Cassandraの分散の機構や、データモデルなどはそのままにして、利用者が普段使い慣れているデータストアをNoSQLとして使える
  • 異なるストレージエンジンのノードからクラスタを構成することで、読み出しと書き込み性能を両立できる

MyCassandraのコアストレージエンジン

今のところ、MyCassandraで扱えるストレージエンジンは以下の3つです。

  • Bigtable(cassandra original)
  • MySQL(mycassandra default)
  • Redis(jredis apiを使用)

以下ではそれぞれのストレージエンジンの差し替え方法と各ストレージエンジンに関する特別な設定について説明します。

共通の設定

ここではcassandraのパラメタ設定については省きます(マニュアルを参考にしてください)。
MyCassandraストレージエンジンの選択は非常にシンプルです。
設定はconf/cassandra.yamlで行います。

cassandra.yamlに以下1行を追加してください。

:
auto_bootstrap: false

database: Bigtable # ←追加

hinted_handoff_enabled: true
:

Bigtable

上のように一行追加するだけで素のCassandraと同じように使えます。

MySQL

データモデルのマッピング

cassandraのデータモデルはkeyspace->columnfamily->columnといったデータ構造になっていますが、
これをmysqlではdatabase->table->fieldに対応付けます。
mycassandraの実装しているmysqlはcolumnfamilyのデータをkey/value形式でストアするため、
mysqlでのスキーマ設定をする必要がありません。

mysqlのコネクション設定

上の設定に加えて以下をcassandra.yamlに追加します。

:
auto_bootstrap: false

database: MySQL
sqlhost: localhost # ←mysqlのhost
sqlport: 3306 # ←mysqlのport
sqluser: mycassandra_user # ←mysqlのmycassandra用user名 
sqlpass: XXXXXXXX # ←mysqlのuser password

hinted_handoff_enabled: true
:
keyspaceの設定

また、MySQLはkeyspaceに対応するmysqlのdatabaseを作成する必要があります。
例えば、"keyspace1","keyspace2"というkeyspaceをスキーマで定義している場合は、

mysql> create system;
mysql> create keyspace1;
mysql> create keyspace2;

というように、databaseを事前に作成します。
systemというdatabaseは、cassandraの内部データ用のkeyspaceなので、これも作成してやります。

column familyの設定

keyspaceと異なり、column familyは自動的に上で作成したdatabase上にtableとして作成されます。
column familyの設定として、cassandra.yamlに以下を追記します。

column_families:
         - name: cf1
           rowkeysize: 16 # keyのサイズ(byte)
           columnfamilysize: 2048 # column familyのサイズ(byte)
           storageenginetype: InnoDB # column familyにマッピングするtableのmysqlストレージエンジン
           compare_with: BytesType
           keys_cached: 10000
                :
         - name: cf2
                :

Redis

Bigtableと同様に一行追加するだけで素のCassandraと同じように使えます。
RedisにアクセスするAPIとしてはjredisを利用しています。

MyCassandraのアーキテクチャ


Cassandraのリクエスト受理とストレージの間にStorage Engine Interfaceを導入しました。
このinterfaceを実装することでストレージエンジンを追加できます。

ストレージエンジンの追加方法

利用者は今説明した3つのストレージエンジンの他に自分で追加できます。

追加方法
  1. jdbcなどデータベースにアクセスするドライバにパスを通す
  2. ストレージエンジンに対応したコードをStorage Engine Interface実装する
  3. cassandra.yamlの設定

以下はRedisのようなKVSをStorage Engine Interfaceを用いて実装した例です。

public class KVSStorageEngine implements StorageInterface
{
  StorageInstance client;
  String keyspace, cf;
  final String KEYSEPARATOR = ":";

  public Instance(String keyspace, String cf)
  {
    client = new KVSClient(<HOST>,<PORT>);
    this.keyspace = keyspace;
    this.cf = cf;
  }
  
  public int put(String rowKey, ColumnFamily newcf)
  {
    String key = keyspace+KEYSEPARATOR+cf+KEYSEPARATOR+rowKey;
    ColumnFamily cf = (client.exists(rowKey) ? updateCF(rowKey, newcf) : newcf);
    return client.set(key, serialize(cf));
  }
  
  public ColumnFamily get(String rowKey)
  {
    String key = keyspace+KEYSEPARATOR+cf+KEYSEPARATOR+rowKey;
    return deserialize(client.get(key));
  }
}

発表スライドなど

研究会やカンファレンスなどで発表した資料を以下に挙げていきます!!
http://www.slideshare.net/sunsuk7tp/edit_my_uploads