Apache Cassandraを試してみる


Cassandraを使う機会があったので，自分の環境で遊んでみます．

# 環境
* Mac OSX El Capitan 10.11.6
* Homebrew

# 概要
## Apache Cassandra
オープンソースの分散DBおよびDBMSでNoSQLに分類される．
[Apache Cassandraの機能およびアーキテクチャの概要 | DataStax Academy: Free Cassandra Tutorials and Training](https://academy.datastax.com/resources/apache-cassandra%25E3%2581%25AE%25E6%25A9%259F%25E8%2583%25BD%25E3%2581%258A%25E3%2582%2588%25E3%2581%25B3%25E3%2582%25A2%25E3%2583%25BC%25E3%2582%25AD%25E3%2583%2586%25E3%2582%25AF%25E3%2583%2581%25E3%2583%25A3%25E3%2581%25AE%25E6%25A6%2582%25E8%25A6%2581)

## Cassandra Cluster Manager(CCM)
一般的に分散DBは，複数のマシンによって処理の負荷分散を行うことが目的となっているため，実際に構築する場合には複数のマシンが必要(VMでも可)．
そんな中，CCMの登場によって1台のlocalhost上で複数のノードを構築できるようになり，テストコードを走らせたりするのに用いる．

# CCMのインストール
Mac で環境構築するのでHomebrewでccmをインストールする．

```bash
brew install ccm
```

Pythonパッケージもあるが，2017年現在では，Python2にしか対応していない．

```bash
pip install ccm
```

# Cassandra Clusterの実装
今回は，試すだけなので3つのノードでクラスタを構成する．

## クラスタの作成
Cassandraクラスタを定義する

```bash
# ccm create <Cluster name> -v <Cassandra Version>
ccm create qiita -v 3.9
```

## nodeごとのIP Addressの設定
各ノードごとにIPアドレスが必要になるが，CCMはlocalhostでのみ動作すれば良いので，127.0.0.XのIPアドレスをlocalloopback(lo0)に複数割り当てれば良い．
今回3nodeあるので，127.0.0.1 ~ 127.0.0.3までのIPを作成する．

```bash
sudo ifconfig lo0 alias 127.0.0.1
sudo ifconfig lo0 alias 127.0.0.2
sudo ifconfig lo0 alias 127.0.0.3
```

## nodeの生成

```bash
ccm populate -n 3
```

## 各ノードの状態を確認
ccm status コマンドで各ノードの状態を確認．

```bash
$ ccm status
Cluster: 'qiita'
----------------
node1: DOWN (Not initialized)
node3: DOWN (Not initialized)
node2: DOWN (Not initialized)
```

ノードを生成したばかりなので，DOWN状態で初期化もされていない．

## ノードの起動・停止
ccm start コマンドでノードの起動．

```bash
# nodeを指定して起動
$ ccm node2 start
$ ccm status
Cluster: 'qiita'
----------------
node1: DOWN
node3: DOWN
node2: UP

# nodeをすべて起動 
$ ccm start
$ ccm status
Cluster: 'qiita'
----------------
node1: UP
node3: UP
node2: UP

# nodeをすべて停止
$ ccm stop
$ ccm status
Cluster: 'qiita'
----------------
node1: DOWN
node3: DOWN
node2: DOWN
```

# CQLの実行
CQL(Cassandra Query Language)を実行してDatabaseを構築する．

```bash
# CQL shell の起動
$ ccm node1 cqlsh
```


## Keyspaceの作成
Keyspaceを作成，Keyspaceの構成及びReplication-factorを設定する．
今回は，1つのデータセンターと仮定してレプリカを構築するためSimpleStrategyを選択．あと，全ノードにデータテーブルをコピーするためreplication_factorは3に指定する．

```bash
# Keyspaceの作成 (keyspace_nameは，Keyspaceの名前)
cqlsh> CREATE KEYSPACE keyspace_name WITH replication = {'class': 'SimpleStrategy','replication_factor':3};
# 使うKeyspaceの選択
cqlsh> USE keyspace_name;
cqlsh:keyspace_name>
```

## Tableの作成
こんなテーブルを作成する．
* テーブル名: table_name
* userid: int型，主キー
* first_name: text型
* last_name: text型

```bash
cqlsh:keyspace_name> CREATE TABLE keyspace_name.table_name ( 
                 ... userid int PRIMARY KEY,
                 ... first_name text,
                 ... last_name text);
```

## データを挿入
作成したkeyspace_nameテーブルにデータを挿入，これは，普通のSQLと変わらないかな・・・

```bash
cqlsh:keyspace_name> INSERT INTO table_name (userid ,first_name, last_name) VALUES (1, 'taro', 'tanaka');
```

## 他のノードを確認
さっきnode1にデータを挿入した．それが共有されてるか他のノードで確認する．

```bash
# node3に接続
$ ccm node3 cqlsh
Connected to qiita at 127.0.0.3:9042.
[cqlsh 5.0.1 | Cassandra 3.9 | CQL spec 3.4.2 | Native protocol v4]
Use HELP for help.
cqlsh> use keyspace_name ;
cqlsh:keyspace_name> SELECT * FROM table_name ;
cqlsh:keyspace_name> 
 userid | first_name | last_name
--------+------------+-----------
      1 |       taro |    tanaka

(1 rows)
```

データが共有されているのでOK!!

## Consistency levelを変更

```bash
cqlsh> CONSISTENCY
cqlsh> Current consistency level is ONE.
```
今は，Consistency levelがOneになっている．
これを，Allに変えて見る.

```bash
cqlsh> CONSISTENCY ALL;
cqlsh> Consistency level set to ALL.
```

ALLに変更したので，全ノードから一致するデータが取得できたらCQLを実行するという形になる．

```bash
# すべてのノードが稼働している場合
$ ccm status
Cluster: 'qiita'
----------------
node1: UP
node3: UP
node2: UP

cqlsh> use keyspace_name ;
cqlsh:keyspace_name> SELECT * FROM table_name ;
cqlsh:keyspace_name> 
 userid | first_name | last_name
--------+------------+-----------
      1 |       taro |    tanaka

(1 rows)

# 1つのノードが死んでいる場合
$ ccm status
Cluster: 'qiita'
----------------
node1: UP
node3: UP
node2: DOWN

cqlsh> USE keyspace_name ;
cqlsh:keyspace_name> SELECT * FROM table_name ;
cqlsh:keyspace_name> CONSISTENCY ALL ;
cqlsh:keyspace_name> Consistency level set to ALL.
cqlsh:keyspace_name> SELECT * FROM table_name ;
cqlsh:keyspace_name> NoHostAvailable: 
```

Consistency levelがAllなので，nodeが1つでも死んでいると，データの取得もできなくなるので，普通はQUORUMが汎用性の高いパラメータになる．

# まとめ
今回は，ccmを用いてApache Cassandraを試してみた，簡単に運用のデモを行ってみた．
技術的な内容は，余力があるときにまとめてみたいと思います．(余力があれば・・・)

# 参考文献
[Apache Cassandraの機能およびアーキテクチャの概要 | DataStax Academy: Free Cassandra Tutorials and Training](https://academy.datastax.com/resources/apache-cassandra%25E3%2581%25AE%25E6%25A9%259F%25E8%2583%25BD%25E3%2581%258A%25E3%2582%2588%25E3%2581%25B3%25E3%2582%25A2%25E3%2583%25BC%25E3%2582%25AD%25E3%2583%2586%25E3%2582%25AF%25E3%2583%2581%25E3%2583%25A3%25E3%2581%25AE%25E6%25A6%2582%25E8%25A6%2581)
[CQLコマンド|CQL for Cassandra 2.x](https://docs.datastax.com/ja/cql-jajp/3.1/cql/cql_reference/cqlCommandsTOC.html)