Aerospikeにaerospike-loaderでデータをバルクロードしてみました

#はじめに
ある事情で、既存のNoSQLより10倍速いとうたわれるAerospikeの動作検証をした結果を、メモ代わりに残しておきたいと思います。
ここではホントに10倍速いのか？という検証はしませんが、
インストールからaerospike-loaderを使用したデータ投入、確認までを実施していきます。

Aerospikeは2014年6月にオープンソースとして公開されていますが、
情報としてはそれほど多くなく（Qiitaにも投稿はいくつかあります）、
本家サイトのドキュメント（ http://www.aerospike.com/docs/ ）は頼りになる存在です。

また今回は動作検証にDockerを用いました。
https://github.com/aerospike/aerospike-server.docker
にDebianのDockerfileがあるのですが、CentOSのイメージも欲しいなと思いまして、
https://github.com/takexi/Aerospike
にCentOS7のイメージを作成するDockerfileを置いてます。（ほとんどDebian版と同じです）
検証で使用した限りでは、両者に動作の違いは見受けられませんでしたので、
どちらを使用しても良いかと思います。
当初はサーバとクライアントを別のマシンで検証しようと思っていたのですが、
だんだん面倒くさくなってサーバ側をDockerにしちゃいました。てへ。


#0.前提
対象のマシンに、以下をインストールしておいてください（DockerはServiceを起動しておいてください）。
なお、今回は対象のマシンにCentOSを使用しています。
クライアント：CentOS <---> サーバ：Dockerコンテナ という構成になります。

- Docker

```bash:以下インストール例
sudo yum install epel-release -y
sudo yum install docker-io -y
```

- unzip

```bash:以下インストール例
sudo yum isntall unzip -y
```

- Java1.6以上 ※後述のaerospike-loaderで使用します

```bash:以下インストール例
sudo yum isntall java-1.8.0-openjdk-devel.x86_64 -y
```

# 1.DockerにてAerospikeのインストール
上記のgithubからDockerfileとaerospike.confを取得・配置し、以下にてbuildします。

```
sudo docker build -t aerospike ./
```

# 2.Aerospike起動
/opt/aerospike/dataをデータの配置場所とします（変更可能ですが、aerospike.confや本ページで必要と思われる箇所を適宜修正してください）。

```
sudo mkdir -p /opt/aerospike/data
sudo docker run -ti --rm --ulimit nofile=64000:64000 -v /opt/aerospike/data:/opt/aerospike/data --name aerospike -p 3000:3000 -p 3001:3001 -p 3002:3002 -p 3003:3003 aerospike
```
ulimitをここで設定しているのがポイントです。
aerospike.confのproto-fd-maxとともに、十分に大きい値にしておかいないと、
Aerospikeが起動しません。

# 3.クライアント側に各種ツール（aerospike-tools,aerospike-loader）をインストール
適当なディレクトリ（ここでは例として/opt）にインストールします。

```
cd /opt
curl http://www.aerospike.com/artifacts/aerospike-tools/3.6.3/aerospike-tools-3.6.3-el6.tgz |sudo tar zxv
cd aerospike-tools-3.6.3-el6
sudo ./asinstall
```

```
cd /opt
curl http://ftp.riken.jp/net/apache/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.tar.gz |sudo tar zxv
```

```
sudo curl -o aerospike-loader-master.zip https://codeload.github.com/aerospike/aerospike-loader/zip/master
sudo unzip aerospike-loader-master.zip
cd aerospike-loader-master
```

このままmavenを実行してインストールを完了したいのですが、
**執筆時点（2015/12/13）で2点ほど修正しないと、testが通らずインストールできません。**

- 修正点1

integerValidation.jsonの、8行目の"set"の部分にtypeを入れるのと、13行目のcolumn_positionを3に修正します。


```
sudo vi src/test/resources/integerValidation.json
{
        "version" : "1.0",
        "input_type" : "csv",
        "csv_style": { "delimiter": "," , "n_columns_datafile": 3, "ignore_first_line": true },

        "key": {"column_name":"key", "type": "String"},

        "set": {"column_name":"set", "type": "string"},


        "binlist": [
            {"name": "age",
                "value": {"column_position": 3, "type" : "integer"}
                }
        ]
}
```

- 修正点2

listValidation.jsonの、17行目のllistをlistに変更します。これはtypoと思われますね。

```
sudo vi src/test/resources/listValidation.json
{
        "version" : "1.0",
        "input_type" : "csv",
        "csv_style": { "delimiter": "," , "n_columns_datafile": 5, "ignore_first_line": true },

        "key": {"column_name":"key", "type": "String"},

        "set": { "column_name":"set" , "type": "string"},


        "binlist": [

        {"name": "segments",
        "value": {"column_name": "segments", "type" : "list"}
        },
        {"name": "l-segments",
        "value": {"column_name": "l-segments", "type" : "list"}
        },
            {
              "name":"name",
              "value": {"column_name": "name", "type" : "string"}
            }
        ]
}
```

上記２つのファイルを修正後、以下を実行します。


```
sudo /opt/apache-maven-3.3.9/bin/mvn clean install
```


以下の文字列が表示されればインストール成功です。
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------



# 4.Aerospikeのデータ構造（参考）
詳細は http://www.aerospike.com/docs/architecture/data-model.html にありますが、
以下の図のように、namespaceの中にsetがあり、setの中にrecordがあります。recordは複数のbin（keyに対するvalue）を持てます。
![gazo01.png](https://qiita-image-store.s3.amazonaws.com/0/85163/d3f96973-42e3-b66a-25a7-40a09c4709ef.png)

RDBでいくと、データベース=namespace、テーブル=set、行=record、列＝bin といった形でしょうか。
なお今回は、namespace名：test set名：set です。


# 5.Aerospikeにデータ投入、確認
- データを準備します。

今回は横浜市統計ポータルサイト（http://www.city.yokohama.lg.jp/ex/stat/opendata/toroku02.html ）
のオープンデータ：男女別人口及び世帯数－町丁　を使用します。
ヘッダ部分にマルチバイトが使用できないので、下記のように英語に置き換え、utf-8nで保存します。（ファイル名はr2yokohama1510.csvとします）

```
date,code,area,households,population,populationm,populationf
2015/10/31,141003,横浜市,1736764,3729563,1857358,1872205
2015/10/31,141011,鶴見区,140442,287571,148597,138974
2015/10/31,141020,神奈川区,119813,234393,118750,115643
2015/10/31,141038,西区,53866,97882,48994,48888
2015/10/31,141046,中区,83837,150839,78297,72542
2015/10/31,141054,南区,104027,198916,99318,99598
2015/10/31,141119,港南区,97640,216782,106078,110704
2015/10/31,141062,保土ケ谷区,97782,204596,101590,103006
2015/10/31,141127,旭区,112219,249024,122207,126817
2015/10/31,141071,磯子区,79304,167840,82757,85083
2015/10/31,141089,金沢区,91230,202378,99503,102875
2015/10/31,141097,港北区,164485,338812,169450,169362
2015/10/31,141135,緑区,78540,179640,89118,90522
2015/10/31,141178,青葉区,131216,308156,150659,157497
2015/10/31,141186,都筑区,83909,211918,106080,105838
2015/10/31,141101,戸塚区,120302,276432,136762,139670
2015/10/31,141151,栄区,55231,123314,60667,62647
2015/10/31,141160,泉区,67647,155195,76551,78644
2015/10/31,141143,瀬谷区,55274,125875,61980,63895
```

Aerospike側の定義がこちら。（yokohama.jsonという名前で保存します）

```
{
  "version" : "1.0",
  "input_type" : "csv",
  "csv_style": { "delimiter": "," , "n_columns_datafile": 7, "ignore_first_line": true}

  "key": {"column_name":"code", "type": "string"},

  "binlist": [
    {"name": "date",
     "value": {"column_name": "date", "type" : "String"}
    },
    {"name": "code",
     "value": {"column_name": "code", "type" : "String"}
    },
    {"name": "area",
     "value": {"column_name": "area", "type" : "String"}
    },
    {"name": "households",
     "value": {"column_name": "households", "type" : "integer"}
    },
    {"name": "population",
     "value": {"column_name": "population", "type" : "integer"}
    },
    {"name": "populationm",
     "value": {"column_name": "populationm", "type" : "integer"}
    },
    {"name": "populationf",
     "value": {"column_name": "populationf", "type" : "integer"}
    }
  ]

}
```

- aerospike-loaderを使用して、ロードします。

```
cd /opt/aerospike-loader-master
sudo ./run_loader -h 対象のマシンのIP -p 3000 -n test -s set -c /path/to/yokohama.json /path/to/r2yokohama1510.csv
```

Aerospike loader completed
が表示され、ERRROの文字列がなければ登録完了です。

- データが登録されていることを、SQLライクなツールであるaqlで確認します。

```
aql
aql> select * from test.set
+--------------+----------+-------------------+------------+------------+-------------+-------------+
| date         | code     | area              | households | population | populationm | populationf |
+--------------+----------+-------------------+------------+------------+-------------+-------------+
| "2015/10/31" | "141003" | "横浜市"       | 1736764    | 3729563    | 1857358     | 1872205     |
| "2015/10/31" | "141054" | "南区"          | 104027     | 198916     | 99318       | 99598       |
| "2015/10/31" | "141151" | "栄区"          | 55231      | 123314     | 60667       | 62647       |
| "2015/10/31" | "141101" | "戸塚区"       | 120302     | 276432     | 136762      | 139670      |
| "2015/10/31" | "141135" | "緑区"          | 78540      | 179640     | 89118       | 90522       |
| "2015/10/31" | "141097" | "港北区"       | 164485     | 338812     | 169450      | 169362      |
| "2015/10/31" | "141186" | "都筑区"       | 83909      | 211918     | 106080      | 105838      |
| "2015/10/31" | "141020" | "神奈川区"    | 119813     | 234393     | 118750      | 115643      |
| "2015/10/31" | "141143" | "瀬谷区"       | 55274      | 125875     | 61980       | 63895       |
| "2015/10/31" | "141046" | "中区"          | 83837      | 150839     | 78297       | 72542       |
| "2015/10/31" | "141062" | "保土ケ谷区" | 97782      | 204596     | 101590      | 103006      |
| "2015/10/31" | "141071" | "磯子区"       | 79304      | 167840     | 82757       | 85083       |
| "2015/10/31" | "141038" | "西区"          | 53866      | 97882      | 48994       | 48888       |
| "2015/10/31" | "141127" | "旭区"          | 112219     | 249024     | 122207      | 126817      |
| "2015/10/31" | "141160" | "泉区"          | 67647      | 155195     | 76551       | 78644       |
| "2015/10/31" | "141089" | "金沢区"       | 91230      | 202378     | 99503       | 102875      |
| "2015/10/31" | "141119" | "港南区"       | 97640      | 216782     | 106078      | 110704      |
| "2015/10/31" | "141011" | "鶴見区"       | 140442     | 287571     | 148597      | 138974      |
| "2015/10/31" | "141178" | "青葉区"       | 131216     | 308156     | 150659      | 157497      |
+--------------+----------+-------------------+------------+------------+-------------+-------------+
19 rows in set (0.018 secs)
```

登録されたことを確認できました。
aqlはselectのほかに、insert,deleteなど数多くの機能を持っています。
以下deleteで、横浜市のデータが削除されます。
```
delete from test.set where pk = '141003'
```


最後になりましたが、
Aerospikeはレプリケーションがマルチマスタということもあり、運用面も考えられている印象で、利用価値は高いと考えています。
MongoやDynamoDBの対抗馬として、良い感じだと思っています。


余談ですが、当初はバルクロードにembulkを使おうと思っていたのですが
うまくいかず、aerospike-loaderを使用することにしました。
このあたりについては別途時間があれば書きたいと思います。