HTTPで読み書きできるデータベース「Riak」を使ってみる


![Riak-logo.png](https://qiita-image-store.s3.amazonaws.com/0/889/e3dd1968-a7b7-91e8-bd06-00c5ff66e746.png "Riak-logo.png")


# Riakとは?

* 分散型キーバリューデータベース
* HTTPで読み書きする
* 単一障害点がなく耐障害性がある
* スケールが容易

# MacにRiakを入れてみる

```
brew install riak
```

ulimit -n の値を増やす(OSX Lionの場合。ほかは[公式ドキュメント](http://docs.basho.com/riak/1.3.1/cookbooks/Open-Files-Limit/#Mac-OS-X)を参照)

```
sudo vim /etc/launchd.conf
```

```txt:/etc/launchd.conf
limit maxfiles 16384 32768
```

Macを再起動する

```
riak start
```

Riakとやりとりできることを確認する。(ここではhttpieコマンドを使う)

```
http -v localhost:8098/ping
```

```http
GET /ping HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate, compress
Host: localhost:8098
User-Agent: HTTPie/0.6.0



HTTP/1.1 200 OK
Content-Length: 2
Content-Type: text/html
Date: Tue, 17 Dec 2013 08:18:22 GMT
Server: MochiWeb/1.1 WebMachine/1.10.0 (never breaks eye contact)

OK
```

# RiakのURLのパターン

Riakはキーバリューストアで、キーに対応した値をストアできる。キーはバケツというカテゴリに分類される。バケツを分けることで、同じ名前のキーが衝突するのを避けることができる。

```
http://サーバー:ポート/buckets/バケツ/keys/キー
```

RiakはAmazonのDynamoの論文から着想を得ているせいか、RiakのURLはAWSのS3のものと似ている。


# 値を突っ込んでみる

例として、千葉市中央区の統計情報をchibaバケツに突っ込んでみる。


キーを指定する場合はPUTメソッドを使う

```shell
http -v PUT localhost:8098/buckets/chiba/keys/chuoku name=中央区 male_population=102080 female_population=100133 km2=44.81                                                                                                               

```

```http:HTTPリクエスト
PUT /buckets/chiba/keys/chuoku HTTP/1.1
Accept: application/json
Accept-Encoding: gzip, deflate, compress
Content-Length: 106
Content-Type: application/json; charset=utf-8
Host: localhost:8098
User-Agent: HTTPie/0.6.0

{
    "female_population": "100133",
    "km2": "44.81",
    "male_population": "102080",
    "name": "中央区"
}
```
```http:HTTPレスポンス
HTTP/1.1 204 No Content
Content-Encoding: gzip
Content-Length: 0
Content-Type: application/json; charset=utf-8
Date: Wed, 18 Dec 2013 04:58:50 GMT
Server: MochiWeb/1.1 WebMachine/1.10.0 (never breaks eye contact)
Vary: Accept-Encoding
```

次に、さきほどの中央区のデータを取り出してみる。取り出すときはGETメソッド。

```shell
http -v GET localhost:8098/buckets/chiba/keys/chuoku
```

```http:HTTPリクエスト
GET /buckets/chiba/keys/chuoku HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate, compress
Host: localhost:8098
User-Agent: HTTPie/0.6.0
```

JSONデータがそのまま返ってくる。

```http:HTTPレスポンス
HTTP/1.1 200 OK
Content-Encoding: gzip
Content-Length: 97
Content-Type: application/json; charset=utf-8
Date: Wed, 18 Dec 2013 07:45:12 GMT
ETag: "7HSboJBKuhPcawi77OYPcl"
Last-Modified: Wed, 18 Dec 2013 07:44:45 GMT
Link: </buckets/chiba>; rel="up"
Server: MochiWeb/1.1 WebMachine/1.10.0 (never breaks eye contact)
Vary: Accept-Encoding
X-Riak-Vclock: a85hYGBgzGDKBVIcypz/fgZtYNLMYEpkyWNlyD2neoYvCwA=

{
    "female_population": "100133",
    "km2": "44.81",
    "male_population": "102080",
    "name": "中央区"
}
```

# 存在しないキーのデータを取り出してみる

```shell
http -v GET localhost:8098/buckets/chiba/keys/shinjukuku
```

```http:HTTPリクエスト
GET /buckets/chiba/keys/shinjukuku HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate, compress
Host: localhost:8098
User-Agent: HTTPie/0.6.0
```

404ステータスがかえってくる

```http:HTTPレスポンス
HTTP/1.1 404 Object Not Found
Content-Length: 10
Content-Type: text/plain
Date: Wed, 18 Dec 2013 05:05:50 GMT
Server: MochiWeb/1.1 WebMachine/1.10.0 (never breaks eye contact)

not found

```

# キーの一覧を取得してみる

まずは、複数のキーを登録する

```shell
http -v PUT localhost:8098/buckets/chiba/keys/hanamigawaku \
	name=花見川区 male_population=89369 female_population=90329 km2=34.24
http -v PUT localhost:8098/buckets/chiba/keys/inageku \
	name=稲毛区 male_population=78199 female_population=78413 km2=21.25
http -v PUT localhost:8098/buckets/chiba/keys/wakabaku \
	name=若葉区 male_population=76159 female_population=75006 km2=84.21
http -v PUT localhost:8098/buckets/chiba/keys/midoriku \
	name=緑区 male_population=62042 female_population=63914 km2=66.41
http -v PUT localhost:8098/buckets/chiba/keys/mihamaku \
	name=美浜区 male_population=72806 female_population=76145 km2=21.16
```

キー一覧を取得する。バケツに対して `keys=ture` を指定するとキーの一覧が取得できる。なお `keys=stream` とするとストリームで返してくれるのでデータセットが大きい場合はこちらのほうが安全とのこと。

```
http -v GET 'localhost:8098/buckets/chiba/keys?keys=true'
```

```http:HTTPリクエスト
GET /buckets/chiba/keys?keys=true HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate, compress
Host: localhost:8098
User-Agent: HTTPie/0.6.0
```

```http:HTTPレスポンス
HTTP/1.1 200 OK
Content-Encoding: gzip
Content-Length: 77
Content-Type: application/json
Date: Wed, 18 Dec 2013 07:41:01 GMT
Server: MochiWeb/1.1 WebMachine/1.10.0 (never breaks eye contact)
Vary: Accept-Encoding

{
    "keys": [
        "hanamigawaku",
        "wakabaku",
        "mihamaku",
        "chuoku",
        "midoriku",
        "inageku"
    ]
}
```

# キーを削除する

削除してみる

```shell
http -v DELETE localhost:8098/buckets/chiba/keys/mihamaku
```

```http:HTTPリクエスト
DELETE /buckets/chiba/keys/mihamaku HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate, compress
Content-Length: 0
Host: localhost:8098
User-Agent: HTTPie/0.6.0
```

204レスポンスを返す

```http:HTTPレスポンス
HTTP/1.1 204 No Content
Content-Encoding: gzip
Content-Length: 0
Content-Type: application/json; charset=utf-8
Date: Wed, 18 Dec 2013 05:23:15 GMT
Server: MochiWeb/1.1 WebMachine/1.10.0 (never breaks eye contact)
Vary: Accept-Encoding
```

# HTMLだって置ける

```shell
echo '<!doctype html><meta charset="utf8"><h1>Riak</h1><p>HTMLも置けます</p>' | http -v --form PUT localhost:8098/buckets/my-bucket/keys/riak.html Content-Type:text/html
```

(ここの `--form` を指定しないとhttpieが `Accept: application/json` ヘッダを吐いてしまい、Riakが406 Not Acceptableを返してしまう。)

ブラウザで http://localhost:8098/buckets/my-bucket/keys/riak.html を開くとHTMLが見れる

# 画像も置ける

適当に画像を落としてくる:

```
wget http://128bitstudios.com/images/logo/Riak_logo.png -O riak-logo.png
```

Riakにつっこむ:

```shell
http -v --form PUT localhost:8098/buckets/my-bucket/keys/riak-logo.png Content-Type:image/png < riak-logo.png
```

ブラウザで http://localhost:8098/buckets/my-bucket/keys/riak-logo.png を開くと画像が表示される