プロダクションでRedis Clusterを3年間運用し続けた所感

この記事はドワンゴ第二アドベントカレンダーの12/3です。
前回は、元先輩のyonexさん！まだ記事書かれてないですけど、お待ちしてますからね。
[第2のドワンゴ Advent Calendar 2017 \- Qiita](https://qiita.com/advent-calendar/2017/dwango2)

# はじめに
dwangoでは、10以上のRedis Clusterを利用していて、
同時に私も10くらいのRedis Clusterに関わって(※)います。

※実際に構築・運用していたり、社内サービスに払い出していたり、Redisからの移行相談に乗ったり

この記事では、私の経験から適当にいくつかの所感について書こうと思います。

### 今まで書いたRedis関連の記事
[プロダクションで2年間Redis Clusterを運用してみて \- Qiita](https://qiita.com/maruloop/items/18932dfc4be8778434d2)
[Redis 4\.0の目玉機能解説 \- Qiita](https://qiita.com/maruloop/items/ea3b067d6d32b6dbca3e)
[Redis ClusterのマネジメントツールReddieがすごい \- Qiita](https://qiita.com/maruloop/items/313b0c30dbdeb0b8f9d9)


# その1 Redis 4.0ってプロダクションでもう使っていいの？
自身で検証期間を十分取れないなら、 **やめた方がいいです。**

理由は最近のリリースからも明らかです。
2日間でCRITICALが3つはちょっと。

| 日時 | version | 緊急度|
|---|---|---|
|2017 11/30 13:14:50  | 4.0.3 | critical |
|2017 11/30 18:42:12  | 4.0.4 | critical |
|2017 12/01 16:03:32  | 4.0.5 | critical |

ちなみに更新内容的には、以下のような感じでした。
4.0.3「PSYNC2のバグ直したよ」
4.0.4「PSYNC2のバグ修正いくつか、4.0.3に入れ忘れてたわ」
4.0.5「4.0.4のバグ修正、壊れてたわ」

というわけで、4.0系はまだ使わないほうがいいです。

# その2 Redisのログは何を監視している？
Redisのログは非常に説明的で、あまりシステムによる監視に向いてません。
とりあえず、以下は正規表現で雑にひっかかるようにしています。

#### AOF出力関連
`Asynchronous AOF fsync is taking too long (disk is busy?). Writing the AOF buffer without waiting for fsync to complete, this may slow down Redis.`
AOF出力時にI/O性能が足りない時に出るもの。I/O性能をあげるか、AOF出力を諦めるか、クエリを減らす必要がある。

#### RDB出力関連
`Can't save in background: fork: Cannot allocate memory`
RDB出力時にメモリ確保できなかった時に出るもの。Redisの利用メモリ減らすか、サーバーのメモリ増やすか、サーバーのメモリオーバーコミットを許可するかする必要がある。

# その3 Redis運用にあたり、なんか便利なツールを使っている？
ときどき[sripathikrishnan/redis\-rdb\-tools](https://github.com/sripathikrishnan/redis-rdb-tools)を使って、Redisの中身全体を見ています。
特定のSET型が大きく育ってないか、アプリケーション実装ミスなどでゴミが溜まってないか、、、等。

サービスに入っているRedisにクエリを投げずに、
Redisの永続化ファイルであるRDBを使って、静的に解析する出来るので精神的にも楽ですね。
pipで雑に入れられるのも便利なところ。

# その4 RedisからRedis Cluster(パスワード付き)に移行するには？(停止メンテ前提)
一応公式資料：[Redis cluster tutorial – Redis](https://redis.io/topics/cluster-tutorial)のMigrating to Redis Clusterもあるけど、パスワードなししか対応してない。

### 方法1: パスワードなしで移行した後にパスワードをつける
パスワードのないRedis Clusterならば、redis-trib.rbのimportで移行できます(公式の方法)。
なので、パスワードなしでRedis Clusterを作り、redis-trib.rbで移行した後に
Redis Clusterの全ノードを落として、パスワードをつけてから再起動。

### 方法2: Mass Insertで一気にパスワード付きに移行する
↑で紹介した便利ツールの機能を利用して、RDBファイルからMass Insertします。
https://github.com/sripathikrishnan/redis-rdb-tools#emitting-redis-protocol

ただし、Redis ClusterにMass Insertする際は、全部のmaster nodeに対して行います。
MOVEDのエラーがたくさん出ますが、全部無視してください。

Redis Clusterの各ノードをRedis単体と捉えて、データを移行。
Redis Clusterの機能によって、担当ではないキーにはMOVEDエラーを返す、という仕様を利用しています。

### 方法3: このPRを応援する
[Redis\-Cluster: Add support to auth in redis\-trib\.rb by otherpirate · Pull Request \#4288 · antirez/redis](https://github.com/antirez/redis/pull/4288) 

# その5 Redis Clusterの1node辺りのメモリサイズのオススメはあるの？

例えば、usable 100GBのRedis Clusterを作りたい時に、どちらが良いでしょう？

 1. 1node辺り20GBのRedisを5個用意するか
 - 1node辺り5GBのRedisを20個用意するか

NW的な部分、特にコネクションや帯域に影響が出ない範囲で、後者の横に並べる方をオススメします。
理由は単純で、データサイズに依存して運用に少し手間(※)がかかることがあります。
※[大量データを持つRedisのレプリケーションを作るときにやったこと](https://takeshiyako.blogspot.jp/2015/04/bigdata-redis-replication.html)

20個のRedisを運用するのは手がかからないのか？と言われると悩ましいですが、
少なくとも自動化や監視も、何も考えずに横に増やしていけば良い分、気が楽です。

# その6 Redisに不満点はあるの？
たくさんあるけど、それ以上に便利なので使ってます。

例えば、3.2からprotected modeという機能がつきました。
なんでも、インターネットから見えているRedisが多すぎだから、
デフォルトではパスワードをつけるか、RedisのIPアドレス制限機能をonにしないと
localhost以外からはアクセス出来ないようにしたそうです。

でも、Redisのパスワードって平文通信でやりとりされるので、パスワードが設定されてたとしても
インターネットからアクセス出来て構わないようには思えないですし、
いざパスワードが漏れた時に、パスワードを変更するのにRedisの停止が必要なのは重すぎますよね。
passwordをオンラインで複数追加/削除出来れば、redisは無停止で(=サービスは無停止で)変更できるのに。。。と
[config requirepass now accepts multiple passwords](https://github.com/antirez/redis/pull/3419)のPRに+1いただけると良いと思います。

# 最後に
取り留めもなく、まとまりもなく、所感という形でRedisについて書いてみました。
色々不満なところ・不便なところを書きましたが、Redisは私は結構好きなミドルウェアですので、これからも使っていこうと思います。


異論反論ご指摘等ありましたら、コメントにどうぞ。