プロダクションで2年間Redis Clusterを運用してみて

# TL;DR
- Redis Clusterで運用は本当に楽になった
 - でも、Redis 4.0は不安
- Redis Clusterで一番怖いのはDisk IO
 - 特にフェイルオーバーなどのFull Resync時

---
# Redisとは？
- 高速なインメモリ型のKVS
- シングルスレッド
- 豊富なデータ構造(次ページにて詳細)
- 豊富な操作(次々ページにて詳細）

---
## 豊富なデータ構造
- key-value型
- hash型(key-field-value)
- set型(集合演算ができる)
- sorted set型(スコア付きset)
- 任意の型(redis modules機能)

---
## 豊富な操作
- インクリメントや和集合などなど
- lua scriptも実行できちゃう
  - シングルスレッドだからatomicな処理になる
 
---
## Redisの問題点
- writeがスケールしない
- 気軽に停止できない
  - サーバー再起動やバージョンアップなど

---
## Redis Cluster登場
- キーごとに水平シャーディング
  - writeがスケールする！
- 無停止フェイルオーバーができる
  - サーバーの停止ができる！
  - Redisのバージョンアップができる！

---
## Redis Clusterの問題点
- multiple key操作がしにくくなった

##### Redisではできた
```
del key1 key2 key3
```

#### Redis Clusterではしにくい
同じスロット(※)に割り当てられたキーにしか出来ない。
↓は一応できる。
```
del {key}1 {key}2 {key}3
```

##### スロット(slot)
- redis clusterのシャーディングする際の単位
- cluster全体で16384個のslotを持つ
- ある特定のキーはhash計算され、いずれかのスロットに割り当てられる
- multiple key操作は、同一スロット内にしか行えない
- キー名の一部を`{}`で囲むと、`{}`内に囲まれた文字でhash計算される
  - つまり、同一のスロットに明示的に割り当てられる
  - key1とkey2は別スロットになるが
  - {key}1と{key}2は同じスロットになる

---
## Redis Clusterの問題点2
- リソースを富豪的に使う

---
### リソースを相当富豪的に使う
- メモリ使いすぎ
- 既定値では、masterがactive,slaveはstandby
- slaveに持たせている分のデータは利用されない
  - slaveにreadを向かせたい場合は、設定変更が必要
  - クライアントライブラリの対応も必要

---
### リソースを相当富豪的に使う2
- 機材使いすぎ
- Redis Clusterの最小推奨構成はmaster3/slave3
  - 物理サーバー故障も考えると、サーバー筐体3台必須
  - なぜmaster3/slave3が最小推奨構成かは後述

---
### ここまでがRedis Clusterの概要
---
### ここからが運用していく中で感じたこと
---
## 結局、推奨構成は？
- masterは3ノード以上の奇数
- masterとslaveの比率は1:2以上

---
### why?masterが3ノード以上の奇数？
masterの数を増やすと

- writeが分散される
- **複数のmasterが同時にダウン**した時の可用性が向上する

---
### 障害時にslaveの昇格投票ルール
- 全masterのうちの過半数の賛成票が必要

##### 例えば
- 3masterでClusterを組むと
  - 2master同時にダウンすると、生きているmasterは1つ
  - つまり、過半数(2つ以上)の賛成票は絶対得られない
- 4masterでClusterを組むと
  - 2master同時にダウンすると、生きているmasterは2つ
  - つまり、過半数(3つ以上)の賛成票は絶対得られない
- 5masterでClusterを組むと
  - 2master同時にダウンすると、生きているmasterは3つ
  - つまり、過半数(3つ以上)あの賛成票を**得られる**

※最小推奨構成がmaster3/slave3なのは、この投票ルールのせい

---
### masterを3ノード以上の奇数にするのは
同時にmasterがダウンした時にも
サービス継続できるようにするため。

---
### why?masterとslaveの比率は1:2以上？
- **masterが連続でダウン(not同時)**した時の可用性が向上する

---
##### slaveの融通(レプリカマイグレーション)
**masterとslaveの比率が1:1だったら？**
masterがダウンし、slaveが昇格した後、
昇格した元slaveには、slaveはいない。

つまり、昇格した元slaveが単一障害点になる。


**masterとslaveの比率が1:2以上なら**
slaveを持っていない単一障害点のmasterには、他のslaveを複数持つmasterから、slaveを自動で融通してもらえる。

---

### master:slave比率を1:2以上にするのは
連続でmasterがダウンした時にも、
サービス継続できるようにするため。

--- 
### Redis Clusterの可用性まとめ
例えば、
Redis 15インスタンス(5master,10slave)構成では

- masterが2ノード同時に落ちても、サービス継続できる
- 悲観的に適当な6ノードが連続で落ちても、サービス継続できる


**つまり、夜に熟睡できる！**

---
### Redis Clusterのイケてないところ
- Disk IOが激しい

可用性のためのmaster昇格やslave融通の際、
毎回Full Resyncが走る。


Full Resyncが走れば、Redisのバックアップファイルである
RDBやAOFのDisk Writeがバカにならない。
(つらい、上手いこと部分同期してくれ)

##### 実際にあった事例
Disk IOが詰まり、masterノードが死と判定され、
slaveが昇格。

slave昇格時のDisk IOがやっぱり詰まり、またすぐに死判定され、
また別のslaveが昇格。連鎖的に昇格祭り。

**解決方法**
- Disk IOの遅さを改善したり(RAID ControllerやSSD)
- そもそも大きなデータを減らしたり
- AOFやRDBのバックアップを停止させたり

---
### 今後のRedis Clusterの不安事
- 現在Redis最新は3.2.6
- 開発中のは4.0.0-RC2
- 3系と4系を混ぜてCluster組めないっぽい

3系で作ったClusterから4系への移行、どうしよう。
今から新規に組むなら、4系を待つ選択肢も。

---
### その他
- フェイルオーバー(昇格)の検知は、nodes.confファイルのタイムスタンプで検知できる
- Cluster組む前に色々、redis.confは設定すべき
  - ノードが死んだと判断されるまでの秒数
  - 1ノードが死んだ時にCluster全体を死ぬ判定にするか、そのノードを担当していたキーだけを死んだ判定にするか
  - 細かい設定は[Redis cluster tutorial](https://redis.io/topics/cluster-tutorial)参照
- Redisのノード間の通信(GOSSIP)の非効率さ、なんとかならないのか・・・
  - ノードIDが無駄に長いせいなんだけど・・・

---
### まとめ
- Redis Clusterで夜、安心して眠れる
- 3系から4系への移行どうしよう
- 良きRedis Clusterライフを