RailsのセッションストアとしてRedisを使う(Mac/EC2:AmazonLinux)


RailsデフォルトのCookieを使うセッションストアから、Redisに変更してみる。
ローカル開発環境(Mac)と、本番環境(EC2:AmazonLinux)の両方動くようにする。
なお、本番環境ではRedisサーバとしてElastiCacheを使った。

## Redisとはなんぞや？
いわゆるひとつのDB。といってもPostgresqlやMySQLといったRDBとは毛色が違っていて、

* 一意のキーと、保存したい値のペアでデータを保存する(KVS:KeyValueStore)
* データを全てメモリ上に持つ（なので動作が高速）

という特徴がある。

でもメモリにあるってことは再起動するとデータ消えるんでしょ？と思いきや、定期的にメモリ上のデータのスナップショットを保存してくれる（データ永続化）。もちろんクラッシュ時には最後にスナップショットを保存してから先の分は消えてしまうけど、それを最小限に抑えるようにもできるとのこと。

また、レプリケーションにも対応している。
レプリケーションというのは、複数のDBを用意して、内容を常に同期させておくこと。負荷分散になるし、障害にも強くなる。
そしてこのレプリケーション、AWSのElastiCacheでサポートされている。（←レプリケーションまだやってないけど、今回はこれが決め手）

## MacにRedisをインストール
### Redisのインストール
homebrewを使ってインストール。

```
% brew install redis
```

一応バージョン確認してみる。

```
% redis-server --version
Redis server v=2.8.13 sha=00000000:0 malloc=libc bits=64 build=96319fcc2102d7fa
```

Redisサーバ起動。(`Ctrl-C`で終了)

```
% redis-server /usr/local/etc/redis.conf
```

### Redisが自動実行されるよう登録
これでも動くけど、ローカルでRailsアプリを動かすたびにRedisサーバを起動しないといけなくなる。
それは面倒なのでRedisサーバが自動実行されるよう登録する。

```
% ln -sfv /usr/local/opt/redis/*.plist ~/Library/LaunchAgents
% launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.redis.plist
```

念のためプロセスを確認してみる。

```
% ps ax | grep redis-server
13443   ??  S      0:00.44 /usr/local/opt/redis/bin/redis-server 127.0.0.1:6379
13836 s005  S+     0:00.00 grep redis-server
```

これでMacを再起動しても自動でRedisサーバが起動してくれる。

自動起動をやめたいときはコチラ。

```
% launchctl unload -w ~/Library/LaunchAgents/homebrew.mxcl.redis.plist
```

## RailsにRedisを導入
Gemをインストール

```Gemfile
gem 'redis'
gem 'redis-rails'
```

セッションストアをRedisにする。

初期設定はコメントアウト。

```config/initializers/session_store.rb
#Rails.application.config.session_store :cookie_store, key: 'XXXXXX'
```

そしてdevelopmentとproductionで設定を分けたいので、セッションストアの設定を`development.rb`に移動

```config/environments/development.rb
Rails.application.configure do
  # (中略)
  # これを追加
  config.session_store :redis_store, servers: 'redis://localhost:6379/0', expire_in: 1.day
end
```

`redis://localhost:6379/0`の`0`というのはRedisのDBのIDとのこと。0~15まであるらしい。
もし他の用途でもRedisを使うなら、そこでは別の数字を使うといいのかな。
`expire_in`はセッションデータの生存期間。この場合1日経つと消える。

これでローカル開発環境(Mac)は動くはず。

## Redisに保存されたデータを確認
せっかくなので、保存されたセッションデータを確認してみる。

Redisクライアントを起動。

```
% redis-cli
```

もしID`0`以外のDBを指定していたら、DBを選択。

```
127.0.0.1:6379> select 1
```

DBに保存されているキーの数を取得

```
127.0.0.1:6379> dbsize
```

キーを取得

```
127.0.0.1:6379> keys *
1) "f1412e2bbe5df2091ebdf2e3025e2335"
```

キーが表示されるので、そのキーを使って値を見てみる。

```
127.0.0.1:6379> get "f1412e2bbe5df2091ebdf2e3025e2335"
```

読めない文字列が出てくるけど、何かしら保存されてる。

ちなみに`flushdb`を実行すると、RedisのDBのデータが全削除される。
Railsアプリにログイン機能があったりすると、セッションデータが無くなってログインし直しに。
これで本当にRedisに保存されていることを実感。

```
127.0.0.1:6379> flushdb
```

終了する。

```
127.0.0.1:6379> exit
```

## EC2:AmazonLinux - ElastiCacheでも動かす
ローカルでうまくいったら、本番環境でも動かしてみる。
本当はローカルからもElastiCacheを使いたかったけど、今のところElastiCacheはEC2ネットワーク外からはアクセス出来ないらしい。

### ElastiCacheのエンドポイントを確認
ElastiCacheの作成手順は割愛。
ただ、CacheClusterの名前は、EC2等と違って後から名前の変更ができないので注意。

作成したらこんな感じ。

![スクリーンショット 2014-09-22 22.50.02.png](https://qiita-image-store.s3.amazonaws.com/0/39565/6c8bb140-1d76-3aed-7085-7cc4855479a7.png "スクリーンショット 2014-09-22 22.50.02.png")

画像中の`1node`となっているリンクから、ノードの詳細画面に移動

![スクリーンショット 2014-09-22 22.54.14.png](https://qiita-image-store.s3.amazonaws.com/0/39565/2d8b8258-078a-748b-177c-f8a8317d4725.png "スクリーンショット 2014-09-22 22.54.14.png")

ここで、エンドポイントの文字列をコピーしておく

### 本番環境用のセッションストア設定

```config/environments/production.rb
Rails.application.configure do
  # (中略)
  # これを追加
  config.session_store :redis_store, servers: 'redis://XXXX.XXXX.XXXX.XXXX.cache.amazonaws.com:6379/0', expire_in: 1.day
end
```
`XXXX.XXXX.XXXX.XXXX.cache.amazonaws.com`の部分がエンドポイント。
あとはデプロイすれば本番環境でも動くはず。