DBのあるべき姿の冗長構成
みなさんはDBの冗長構成を取っていますか?
冗長構成とは簡単に言うと、
システムやサービスの障害が発生した場合に、自動的に別のバックアップシステムやリソースに切り替え、中断を最小限に抑える仕組み
になります。
冗長構成を取っていると DB に障害が発生した際でも被害を最小限に抑えてシステム運用することが可能となっています。
データに破損が起きると案件次第では損害賠償に発展したり、ユーザーへの悪影響が生じたりするなどビジネスチャンスを失ってしまいます。
可能な限り冗長構成を取るようにしましょう〜
RDS for MySQL でフェイルオーバー試してみた
RDS はちゃんとお金かかります!
自分で払える範囲のスペックで構築してください!
後、検証が終わったら RDS は閉じてください!!!
※RDS は停止してもお金がかかります。。。。(インスタンス料金, データベースストレージ料金, バックアップストレージ料金)
事前準備
EC2 と RDS の構築は済まして置いてください。
その上で1秒毎にDBへデータを登録する処理を PHP で書いていきます。
<?php
ini_set('mysqlnd.net_read_timeout', 3);
$i = 0;
$end_time = time() + 600;
while (time() < $end_time) {
$result = hoge();
sleep(1);
echo $i . ":" . $result . "\n";
$i++;
}
function hoge () {
$result = 'connectionWaiting';
try {
$dbh = new PDO(
'mysql:host=database-1.cizcjskkh2r7.ap-northeast-1.rds.amazonaws.com;dbname=testDB;charset=UTF8mb4',
'admin',
'password',
);
$dbh->setAttribute(PDO::ATTR_TIMEOUT, 3);
$sql = "INSERT INTO testTable (created) VALUES ('" . date('Y-m-d h:i:s') . "')";
if ($dbh->query($sql)) {
$result = 'Succees';
} else {
$result = 'Faile';
}
} catch (PDOException $e) {
$request = 'Die';
}
return $result;
}
?>
いざ実行
PHPの実行
php index.php
RDS の再起動
RDS はフェイルオーバー での再起動ができるので、フェイルオーバーのオプションを付けて再起動を行います。
まずはデータ登録処理のPHPを実行します。
フェイルオーバー実行前のデータ↓
mysql> select * from testTable;
+----+---------------------+
| id | created |
+----+---------------------+
| 1 | 2023-10-18 10:39:07 |
| 2 | 2023-10-18 10:39:08 |
| 3 | 2023-10-18 10:39:09 |
| 4 | 2023-10-18 10:39:10 |
| 5 | 2023-10-18 10:39:11 |
| 6 | 2023-10-18 10:39:12 |
+----+---------------------+
フェイルオーバー実行後のデータ↓
mysql> select * from testTable;
+----+---------------------+
| id | created |
+----+---------------------+
| 50 | 2023-10-18 10:39:57 |
| 51 | 2023-10-18 10:39:58 |
| 52 | 2023-10-18 10:39:59 |
| 53 | 2023-10-18 10:40:00 |
| 54 | 2023-10-18 10:40:01 |
| 55 | 2023-10-18 10:40:02 |
| 56 | 2023-10-18 10:40:03 |
| 57 | 2023-10-18 10:40:04 | ← 再起動で止まったところと思われる箇所
| 58 | 2023-10-18 10:41:10 | ← 再起動完了したところと思われる箇所
| 59 | 2023-10-18 10:41:11 |
| 60 | 2023-10-18 10:41:12 |
| 61 | 2023-10-18 10:41:14 |
| 62 | 2023-10-18 10:41:15 |
| 63 | 2023-10-18 10:41:16 |
| 64 | 2023-10-18 10:41:17 |
| 65 | 2023-10-18 10:41:18 |
| 66 | 2023-10-18 10:41:19 |
| 67 | 2023-10-18 10:41:20 |
| 68 | 2023-10-18 10:41:21 |
| 69 | 2023-10-18 10:41:22 |
+----+---------------------+
わかったこと
- データは途切れるが、DB の復旧とともにデータ登録が可能となる
- 被害が大きくなりにくい
- エンドポイントが変更されないので、プログラム側で特別な処理は不要(超嬉しい)
- 難しい設定は不要
わかっていないこと
- 大量のデータになった場合の復旧時間
- 今回の検証でもすぐに終わるときもあれば、3分以上かかる場合もあった
- PHP 側に `ini_set(‘mysqlnd.net_read_timeout’, 3)` を入れないと再起動が完了しても処理が継続しない
- RDS 側でデッドロックが走っている?
- 接続先を探している?
- RDS 側に設定が必要?
- とりあえずプログラムでちょっとした工夫は必要そう
まとめ
今回の検証で RDS を使用して冗長性を確保することができたのではないかなぁという所感です〜
実際に検証を通して冗長性のある構成とはこんな感じなんだなぁと言うのがしれたのはかなり大きいです。笑
実際、 DB を使わないシステムは限りなく少ないので DB が死んでも大丈夫と言える構成を取ることでビジネスチャンスを失わないというのはかなり大切だと考えています。
引き続き検証を続けていく必要がありそうです〜