GCPのCloud SQLのフェイルオーバー時の挙動について調べてみる

Google Cloud PlatformのCloud SQL(AWSでいうRDS)のフェイルオーバー時の挙動について調べてみました。
MySQL5.7での動作確認です。

# 公式での説明は

https://cloud.google.com/sql/docs/high-availability?hl=ja

> マスターがあるゾーンが停止状態になると、Cloud SQL は自動的にフェイルオーバー レプリカにフェイルオーバーし、データはクライアントが利用できる状態に維持されます。

マスターが落ちたら自動的にフェイルオーバーレプリカに切り替えてくれるそうです。

> ゾーンの停止状態が発生し、マスターがフェイルオーバー レプリカにフェイルオーバーすると、インスタンスへの既存の接続はすべて切断されます。しかし、アプリケーションは同じ接続文字列や IP アドレスを使用して再接続できます。フェイルオーバー後にアプリケーションを更新する必要はありません。
> 
> フェイルオーバーの後、レプリカはマスターになり、Cloud SQL は、自動的に新しいフェイルオーバー レプリカを別のゾーンに作成します。Cloud SQL インスタンスを Compute Engine インスタンスなどの他のリソースの近くに配置している場合は、元のゾーンが使用可能になった時点で Cloud SQL インスタンスを元のゾーンに再配置することができます。これ以外の場合は、フェイルオーバー後にインスタンスを再配置する必要はありません。

マスターが落ちたら繋がらなくなるけど、アプリ側は更新する必要はない。
用意しておいたフェイルオーバーレプリカが自動的にマスターになり、別のゾーンにフェイルオーバーレプリカが作成される。
ってことらしいです。書かれればその通りなんですが試してみないと、実際の動作はなんとも言えないですね。

# 検証環境

## データベース
高可用性でインスタンスを作成し、マスターとフェイルオーバーレプリカを用意してます。
（IPは隠した方がいいかなと思ったんですが、実験後にインスタンスごと削除したので問題なしということで。）

![db1-min.png](https://qiita-image-store.s3.amazonaws.com/0/235100/77c9bf84-ae42-2fe4-d50a-08e57fcf0a04.png)

## 確認用のVM
適当なVMを用意して、2つのターミナルからマスターとフェイルオーバーレプリカに対して下のmysqladmin pingを実行し続けます。

```
while : ; do mysqladmin ping -h xxx.xxx.xxx.xxx -u root -pxxxxx; sleep 1; date; done
```

下のような感じで接続がどうなるのかが見守ってみます。

![failover1-min.png](https://qiita-image-store.s3.amazonaws.com/0/235100/d2a3dee4-e55d-92a9-9475-ae19ee3f3da1.png)

# フェイルオーバーの実行

Cloud SQLの画面からフェイルオーバーを起こしてみます。

![db2-min.png](https://qiita-image-store.s3.amazonaws.com/0/235100/ab9597d5-12ca-1115-4c81-b57950286552.png)

Cloud SQLの管理画面で一番右上の項目です。

---

![failover2-min.png](https://qiita-image-store.s3.amazonaws.com/0/235100/cc1e1794-c89d-1963-7c86-8f819a63f4c0.png)

**23時26分10秒**

フェイルオーバーを起こしてみると見事にマスターの方に繋がらなくなりました。
フェイルオーバーレプリカの方にはまだ繋がります。

---

![failover3-min.png](https://qiita-image-store.s3.amazonaws.com/0/235100/ae395d01-952f-f056-36aa-a6ff1305d6e0.png)

**23時26分40秒**

マスターの方は繋がったり繋がらなかったりするようになりました。
フェイルオーバーレプリカの方はまだ繋がるようです。

---

![failover4-min.png](https://qiita-image-store.s3.amazonaws.com/0/235100/2cc99149-671a-3a77-8f20-cfd48239a601.png)

**23時28分05秒**

繋がったり繋がらなかったりでしたが、**23時28分05秒**にはマスター側ではエラーもなくなってきました。
ただ、フェイルオーバーレプリカの方では、**23時27分02秒**からコネクション待ちになって繋がらなくなっています。
このタイミングでマスターの内容を元にフェイルオーバーレプリカが再作成されているのではないかと。
フェイルオーバーを発生させたのが**23時26分10秒**なので、マスター側の復旧は**2分ほど**のようです。

---

![failover5-min.png](https://qiita-image-store.s3.amazonaws.com/0/235100/1bc19263-2cd1-4191-1ac4-af3f578b3d21.png)

**23時31分49秒**

ここでようやくフェイルオーバーレプリカの方も繋がるようになりました。
フェイルオーバーを発生させたのが**23時26分10秒**なので、フェイルオーバーレプリカの復旧まで**5分**ほどのようです

---

何回か試してみた結果、
マスターの復旧は**約100秒**、フェイルオーバーレプリカは**約390秒**のようです。
※手動での計測なので、多少のラグがあります。

||1回目|2回目|3回目|4回目|5回目|
|:--|:--|:---|:---|:---|:----|
|マスター|115s|95s|97s|97s|98s|
|フェイルオーバーレプリカ|339s|396s|410s|410s|395s|

# それなりにデータを書き込んでからフェイルオーバーさせてみる

10GB程度、ダミーデータを登録した後にフェイルオーバーを起こしてみると……
マスターの復旧は**101秒**、フェイルオーバーレプリカの復旧は**478秒**でした。
マスターの方はフェイルオーバーレプリカが昇格するということもあり、あまり時間は変わらないようなのですが、
フェイルオーバーレプリカの方は再作成するということもあり、データ容量が増えると時間が増えているようです。

# まとめ
1. Cloud SQLでフェイルオーバーが発生するとフェイルオーバーレプリカがマスターに昇格します。
2. この時、フェイルオーバーレプリカのIPアドレスはマスターのIPアドレスに変更されます。
3. マスター側の復旧は**約100秒**ほどのようです。
4. フェイルオーバーレプリカ側の復旧は**約390秒**ほどのようです。
5. マスターはデータが増えても、復旧までの時間は変わらないようです。
6. フェイルオーバーレプリカはデータが増えると、復旧までの時間が増えていくようです。