Heroku Redisについてまとめてみた

#はじめに
案件でHeroku Redisを使う事が増えてきたため、確認の意味も込めて情報をまとめてみます。
（Google先生の翻訳能力が大幅アップして、本家ドキュメントの情報を読むハードルが下がったのは嬉しい限りです。）

#Heroku Redisとは
Heroku公式のRedisサーバで、アドオンとして追加出来ます。
無料枠から用意されており、以下にプランの一覧が載っています。

[Heroku Redis - Add-ons - Heroku Elements](https://elements.heroku.com/addons/heroku-redis)

また、Private Spacesでの各国のリージョンにも全て対応しています。
ちなみに各アドオンのリージョン対応状況は以下で確認できます。

[Add-on Runtime Availability](https://elements.heroku.com/addons/region-availability)

#CLIツール
Herokuは [Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli) というツールを入れることで、コマンドラインからHerokuを操作出来るようになります。
Redisの確認や設定変更などにはこのツールが必要になりますので、入れておきます。

```
$ heroku plugins:install heroku-redis
```

#モニタリング
以下のリンクから、自分が管理している `Heroku Redis`と`Heroku Postgresql`の一覧が確認出来ます。

<https://data.heroku.com/>

確認したいアプリをクリックすると以下のようにグラフがずらっと確認できます。

<img width="1628" alt="redis01.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/8037/2828bb32-5835-5a55-b371-bd24b579ba87.jpeg">


プランの制限は、 `plan limit` と表示されているので、MAXの数と比較してスケールアップするべきか、などの判断材料となります。
項目はかなりの数ありますので、実際のページで確認してみて下さい。

#環境情報
接続用のアカウント情報は、プラグインをインストールした時点でHerokuの環境変数へ `REDIS_URL` という項目で格納されます。
アプリのダッシュボードから、 `Settings` タブ内の、 `Config Variables` から確認するか、以下のコマンドで一覧を表示可能です。

```
$ heroku config -a {APP_NAME}
=== {APP_NAME} Config Vars
...
REDIS_URL:            redis://h:xxxxxxx@ec2-xxx-xxx-xxx-xxx.compute-x.amazonaws..com:xxxx
...
```

環境情報がURLとして組み立てられており、以下のような構造になっています。

> redis://h:{パスワード}@{ホスト名}:{ポート番号}

Heroku Redisの環境はメンテナンスなどのタイミングでホス名などが変更になります。
それに合わせてこの環境変数も自動で変更が行われるため、コード上で使用する際にはこの環境変数から情報を組み立てる必要があります。
PHPの場合は、 `parse_url` を使用してURLから情報を取得する事が出来ます。

```
$url = parse_url(getenv('REDIS_URL'));
$host = $url['host'];
$port = $url['port'];
$password = $url['pass'];
```

さらに、 [Predis](https://github.com/nrk/predis)のパッケージを使用する場合には、初期化時にそのまま渡してしまって大丈夫です。

```
$redis = new Predis\Client(getenv('REDIS_URL'));
```

#メンテナンス
定期的にメンテナンスが行われており、次回のメンテナンス時間は、ダッシュボードから、 `MAINTENANCE WINDOW` として表示されています。

<img width="906" alt="redis02.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/8037/b1cc2a34-a23a-f319-cc47-29978511b04f.jpeg">


もしくは、コマンドからも確認可能です。

```
$ heroku redis:info -a sushi
=== maturing-calmly-4191 (HEROKU_REDIS_ROSE_URL)
Plan                Premium 0
Status              Available
Created             2015-07-20 20:26 UTC
Timeout             300
Maxmemory           noeviction
Maintenance window: Mondays 22:30 to Tuesdays 02:30 UTC
Persistence:        AOF
```

メンテナンスの必要がない場合は時間が割り当てられおらず、 `not required` と表示されます。

このメンテナンス時間はランダムに割り当てられますが、コマンドから指定が可能です。
（ただし、変更は `Premium` の有料プランでのみ可能）

以下のように設定します。

```
$ heroku redis:maintenance --window="Sunday 14:30"
```

コマンドのヘルプには、

>-w, --window WINDOW # set weekly UTC maintenance window

とあるので、週次のメンテナンス時間の設定、となるようです。

#設定変更
##タイムアウト
タイムアウトの秒数を設定することが出来ます。
デフォルトでは、300秒、となっています。
変更は以下のようにします。

```
$ heroku redis:timeout maturing-deeply-2628 --seconds 60
```

##メモリ容量オーバー時の挙動
保存されているデータが最大メモリ容量をオーバーした場合の挙動を設定することが出来ます。
デフォルトでは、`noeviction`となたっています。

* `noeviction` : エラーを返す
* `allkeys-lru` : 使用頻度の低いキーを最初に削除
* `volatile-lru` : 最初に有効期限が設定されている使用頻度の低いキーを削除
* `allkeys-random` : ランダムにキーを削除
* `volatile-random` : 有効期限が設定されているキーの中からランダムにキーを削除
* `volatile-ttl` : 有効期限の設定されているキーの中で、短い期間が設定されているキーを削除

変更は以下のようにします。

```
$ heroku redis:maxmemory maturing-deeply-2628 --policy volatile-lru
```

#使用方法
蛇足ですが、PHPでの使用例を載せておきます。
Herokuの公式ドキュメントにもある通り、 `Predis` のパッケージを使用します。

・インストール  
以下のようにComposerでインストールします。

```
$ composer require predis/predis
```

・使用  
`autoload`を読み込み、環境変数から接続情報を取得し、初期化します。

```
require '/vendor/autoload.php';
Predis\Autoloader::register();
$redis = new Predis\Client(getenv('REDIS_URL'));
```

コマンドを使って保存や取得などが行なえます。

```
$redis->set('hoge', $data); //セット
$redis->expire('hoge', 100); //期限の設定(秒)
$redis->get('hoge'); //取得
```

使用出来るコマンドはRedisのマニュアルに記載されているものに準拠するようです。  

* [Command reference – Redis](https://redis.io/commands)

#公式ドキュメント

* [Heroku Redis | Heroku Dev Center](https://devcenter.heroku.com/articles/heroku-redis)
* [Heroku Redis Maintenance Windows | Heroku Dev Center](https://devcenter.heroku.com/articles/heroku-redis-maintenance)
* [Understanding Heroku Redis Log Statements and Common Errors | Heroku Dev Center](https://devcenter.heroku.com/articles/redis-logs-errors)