DockerでVoltDB 8.3.1のクラスタ（2台）を構築してみる

# はじめに

[インメモリデータベース　VoltDBの最新バージョン（v8.3.1）をインストールする（クラスタ構成）](https://qiita.com/mkyz08/items/1a1f8c9ce7f91293a5b1)で、VoltDBのクラスタを構築しました。

今回はDocker上で構築してみます。

# VoltDBとは

VoltDBはインメモリRDBで、PostgreSQLに携わったマイケル・ストーンブレーカーにより設定されています。
NoSQLより高速でありながら、SQLを利用できトランザクションもサポートされています。

VoltDB社がCassandraとの性能比較を2017年に実施しており、Cassandraより性能・コスト面で優れていると書かれています。

Comparing Fast Data Performance: A comparison of VoltDB and Cassandra Benchmarks
https://www.voltdb.com/blog/2017/10/02/comparing-fast-data-performance-a-comparison-of-voltdb-and-cassandra-benchmarks/


# 環境・前提条件

・Dockerはインストール済みです。
・VoltDBの設定やモジュールは前述の投稿で記載したものを利用します。
・サーバは2台構成で起動する。
・VoltDBは8.3.1を利用する。

# Dockerイメージを作成する

VoltDBは公式のDockerイメージが公開されています。
ただし、VoltDB 6.6と古いので、公式のDockerfileを修正して8.3.1版を作成します。

なお、ubuntu 14.04がベースになっているので、今回は変更しませんが18.04にしたほうが良いかも。

公式のDockerfileは以下にあります。

https://github.com/VoltDB/voltdb/blob/master/tools/docker/

設定ファイル（deployment.xml）を見ると、デフォルトで冗長化なし（kfactor=0）になっていました。
コンテナ起動時に別設定ファイルを読み込ませることもできますが、今回はこれを使用します。

```deployment.xml
<?xml version="1.0"?>
<deployment>
    <cluster sitesperhost="2" kfactor="0" />
    <httpd enabled="true">
        <jsonapi enabled="true" />
    </httpd>
</deployment>
```

VoltDBのサイトからvoltdb-community-8.3.1.tar.gzをダウンロードし、Dockerfileと同じディレクトリに格納します。

Dockerファイルのタイムゾーンだけ変更しておきます。
※タイムゾーンが書いてあったので思わず書き換えてしまいましたが、docker runのときに「-e TZ=Asia/Tokyo」を指定するだけでよかったです。

```Dockerfile
# Set timezone
ENV TZ=Asia/Tokyo
```

Dockerイメージ（voltdb8.3.1）をビルドします。
「--build-arg VOLT_KIT_VERSION=8.3.1」でバージョンを指定するのがポイントです。

```
docker build --build-arg VOLT_KIT_VERSION=8.3.1 -t voltdb8.3.1 .
```

# コンテナを起動する

以下のコマンドでコンテナを2つ起動させます。

volt1: 192.168.100.11
volt2: 192.168.100.12

にしています。


```
docker network create -d bridge --gateway=192.168.100.254 --subnet 192.168.100.0/24 testnet01
docker network ls
docker network inspect testnet01

docker run --name volt1 --rm -p 18080:8080 -p 21212:21212 -h volt1 --ip 192.168.100.11 --net=testnet01 -e HOST_COUNT=2 -e HOSTS=192.168.100.11,192.168.100.12 voltdb8.3.1

docker run --name volt2 --rm -p 28080:8080 -p 22212:21212 -h volt2 --ip=192.168.100.12 --net=testnet01 -e HOST_COUNT=2 -e HOSTS=192.168.100.11,192.168.100.12 voltdb8.3.1
```

DockerfileでEXPOSEされているポートは以下です。
Client Port（21212）とWeb Interface Port (httpd)（8080）だけ公開しておけば良いはずです（たぶん）
他はVoltDBのサーバ間で使用するポートです。

```
# Expose the following ports
# Client Port                   21212       
# Admin Port                    21211       
# Web Interface Port (httpd)     8080       
# Internal Server Port           3021       
# Replication Port               5555
# Zookeeper port                 7181
# SSH                              22
EXPOSE 22 3021 5555 7181 8080 8081 9000 21211 21212
```

# VoltDBの動作を確認する

VoltDBが動いていることを確認するため、テーブルを作成して、レコードを挿入してみます。

```bash
# docker exec -it volt1 /bin/bash

# sqlcmd
> CREATE TABLE TEST_DATA_TTL (
NAME varchar(50) NOT NULL,
DATA smallint,
CREATED_TIMESTAMP TIMESTAMP DEFAULT NOW NOT NULL,
UNIQUE (NAME),
PRIMARY KEY (NAME)
);
Command succeeded.
> PARTITION TABLE TEST_DATA_TTL ON COLUMN NAME;
Command succeeded.
> insert into test_data_ttl(name, data) values('test001', 1);
(Returned 1 rows in 0.06s)
> select * from test_data_ttl where name = 'test001';
NAME     DATA  CREATED_TIMESTAMP          
-------- ----- ---------------------------
test001      1 2018-09-08 07:11:00.598000 

(Returned 1 rows in 0.02s)

```


# 設定ファイル（deployment.xml）を変更して起動する。

設定ファイル（deployment.xml）を変更する場合、「-v /tmp/deployment-kfactor1.xml:/tmp/deployment.xml」を追加し、コンテナを起動します。

「/tmp/deployment-kfactor1.xml」は入れ替えたいローカル上の設定ファイルを指定します。

```
docker run --name volt1 --rm -p 18080:8080 -p 21212:21212 -h volt1 --ip 192.168.100.11 --net=testnet01 -e HOST_COUNT=2 -e HOSTS=192.168.100.11,192.168.100.12 -v /tmp/deployment-kfactor1.xml:/tmp/deployment.xml voltdb8.3.1

docker run --name volt2 --rm -p 28080:8080 -p 22212:21212 -h volt2 --ip=192.168.100.12 --net=testnet01 -e HOST_COUNT=2 -e HOSTS=192.168.100.11,192.168.100.12 -v /tmp/deployment-kfactor1.xml:/tmp/deployment.xml voltdb8.3.1

```


# おわりに

公式のDockerイメージがあったのであまり苦労せずに構築することができました。
起動後にテーブルを作成していますが、実際にアプリを作成して利用する場合はDockerイメージを作成する際にテーブルやプロシージャは作成しておき、起動するだけでDBを利用可能な状態にしておいたほうが良いですね。