InfluxDB試してみた

MySQLでMetrics系のデータやるのも色々面倒だな～、ということでInfluxDBをかるーく試してみました

## ドキュメント

* http://influxdb.org/docs/
* https://speakerdeck.com/pauldix/the-internals-of-influxdb

Paul Dixのspeakerdeckの資料はとてもわかり易くお勧めです

フォーラム(なにか困ったらまずはここで)
* https://groups.google.com/forum/#!forum/influxdb

## おおまかな仕組み

### Write系

ざっくり言うとWALでログを書きつつ、ShardされたLevelDBやClusterにデータを書き込んでいくという方式です。

### Read系

ちゃんと読んでないけど速度からしてふつーに舐めてConditionにあうものをフィルタリング、グルーピングなどというオーソドックスなクエリエンジンっぽい。
Indexが内部キーとtimeぐらいしかないと思うのでイメージ的に言うとクエリエンジンが限定されたHiveみたいなもんだと思っておいたほうがいいかも。

## 2014/04時点でのその他のデータストアとの比較

### Pros

* Percentileなどが自分で書かなくても利用できる（対MySQL）
* InfluxDB単体でContinueousQueryという定期的にクエリを発行して別seriesに書き出すことができる
* 内部で[Raft](https://speakerdeck.com/benbjohnson/raft-the-understandable-distributed-consensus-protocol)プロトコルを使っており（きっと）耐障害性、クエリの分散に強そうな気がする
* Goなので開発が楽

### Cons

* 開発者、利用者が少ない（まぁ、はじまったばっかだし仕方ないよねー）
* 関数が貧弱(対Hive)
* Indexが実質自由に作れないのでほぼFullScanになる（対RDBMS）
* Replica周りが複雑になりがちっぽいのできちんとどういうふうにShardingされてるか把握してないと障害でた時に死ねそう

## 実際に試してみる

今回は自分たちでビルドして使ってみましょう。大まかなOSXでのビルド手順は下記の通りです

http://influxdb.org/docs/getting_started/building.html

```
git clone https://github.com/influxdb/influxdb.git
brew install protobuf bison flex leveldb go hg bzr
# flexやbisonのversionは自分の環境に合わせてください。ビルドはmacbook proで数分かかります
./configure --with-flex=/usr/local/Cellar/flex/2.5.37/bin/flex --with-bison=/usr/local/Cellar/bison/3.0.2/bin/bison && make
cp config.sample.toml config.toml
./daemon --config=config.toml
```

自分でビルドした場合Adminパネルは付属していません。もしAdminパネルがほしいという場合は http://s3.amazonaws.com/influxdb/influxdb-0.5.8.src.tar.gz 等からadminディレクトリだけを引っ張るかinfluxdb-adminリポジトリをcloneしてビルドしてください。


現時点でのAdminパネルは結果セットが大きいクエリを投げるとブラウザが反応できなくなってしまう玩具です。Curlで大抵管理できちゃうので、そっちで覚えておきましょう。


管理〜Selectまで行える素敵なcliツールはまだ無いので、適当にやるにはcurl(管理系) + influxdb-cli(select)がお手軽です。

```
npm install influxdb-cli -g

# データベースを作る
curl -X POST 'http://localhost:8086/db?u=root&p=root' -d '{"name": "access"}'

# データを挿入する(access DBのevents seriesにstate, email, typeのフィールドを持ったデータを挿入する)

curl -X POST 'http://localhost:8086/db/access/series?u=root&p=root' -d '[
  {
    "name": "events",
    "columns": ["state", "email", "type"],
    "points": [
      ["ny", "paul@influxdb.org", "follow"]
    ]
  }]'

# データベースを削除する
curl -X DELETE 'http://localhost:8086/db/access?u=root&p=root'

# Queryを発行する influxdb-cliがお手軽 (accessデータベースでクエリを発行する)
influxdb-cli -d access
macbook% influxdb-cli -d access
access> Connecting to http://localhost:8086/db/access ...
access> ✔ ready
access> select * from events
┌───────────────┬─────────────────┬───────────────────┬───────┬────────┐
│ time          │ sequence_number │ email             │ state │ type   │
├───────────────┼─────────────────┼───────────────────┼───────┼────────┤
│ 1397872395691 │ 124140001       │ todd@influxdb.org │ ny    │ open   │
│ 1397872395691 │ 124130001       │ paul@influxdb.org │ ny    │ follow │
└───────────────┴─────────────────┴───────────────────┴───────┴────────┘
```

## データ設計

RDBMSというよりは時間軸のデータのIterationが優位なKVSと考えておきましょう。

Indexが実質timeぐらいしかなさそうなのでRDBMSのテーブルに全ツッコミでSecondaryIndexを駆使して高速に検索する、という使い方はできません。Redisなどのようにseriesの命名規則を体系的に行ってtimeのIndexで十分に絞り込めるぐらいのデータ量にしておくほうが確実です。

例えば仮に下のようなテーブルがある場合はそのままの構造でseriesに突っ込むのではなくaccess.[site_id]などで分けておいたほうが当然計算量が少なくなります。

```
CREATE TABLE access (
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  site_id INT UNSIGNED,
  click INT UNSIGNED,
  time timestamp
);
```

ここらへんについてはContinuousQueryでのFauoutなどもできるのでどうやってもいいと思うんですが自分たちのワークロードにあったseriesの設計をしていくのがいいと思います。


## 総評

運用面まで考えるとまだまだ情報が少ないのでよそさまのデータを預かる系は無理だなー、という感じですが自分たちのデータであればApplicationを組む工数を削減するために使うのも有りかな、と感じています。（その分運用で苦労すると思いますが、最悪なくなってもいいやぐらいなら問題ないでしょ）

UDFなどのインターフェースがまだないようなので実際に使う場合は自分達でAggregation Functionの追加などをしてビルドしてデプロイする必要が出てくると思います。

Goが使えてContributionに割く余力があるならRaftプロトコルやLevelDBを使っているという点でエンジニアリング的にとても面白いデータストアだと思います。