こんにちは、プロダクト開発グループの城山です。主にFANSHIPプロダクトのバックエンドを担当しています。
今回はFANSHIPプロダクトで使用しているauroraの移設作業を行ったので、その時に得られた教訓を述べたいと思います。
事の発端
FANSHIPで使用しているとあるDBのパーティション化されたテーブルのレコード数がかなり膨れ上がっており、すでにレコードが最後のパーティションに到達し、そのパーティションにデータが溜まり続ける状態であった。データ量がそのまま膨れ上がり続けると性能劣化、運用効率の低下などの問題をはらむ危険性があったため、パーティションを再構成する必要があった。
なぜ移設なのか?
パーティションを再構成するだけなら稼働しているDBに対しパーティション再構成するためのSQLを流すだけでいいのだが、再構成のSQL自体が何十時間もかかり、その間テーブルロックが発生してしまう。つまりサービスのダウンタイム時間が大きくなってしまう。 なのでできるだけサービスのダウンタイム時間を小さくするために、稼働しているDBのレプリカを作成し、そのレプリカに対してパーティション再構成を行い、稼働しているDBと入れ替える「移設」という選択をとることにした。
システム構成図
書き込みインスタンス、読み込みインスタンスが1台ずつの計2台構成。 書き込み用DNS、又は読み込み用DNSを経由して各サービスからアクセスされる。
移設の流れ
まず初めに移設前DBクラスターに対するレプリケーションを有効にするため、移設前DBクラスターのバイナリログを有効にする。 バイナリログが有効になった後snapshotを取得し、そのsnapshotから新DBクラスターを復元させる。 復元完了後に移設前DBクラスターに対するレプリケーションを開始する。
レプリケーションで同期されたことを確認できたら新DBクラスターに対しパーティションを再構成するためのSQL(ALTER TABLE <table_name> REORGANIZE PARTITION ...
)を流す。
パーティション再構成完了後、移設前DBクラスターへの書き込みを停止するため、書き込み用DNSを読み込みインスタンスに向けかえる。 読み込みインスタンスでは書き込み不可となっているため、結果的に書き込みが停止される(ここでサービスダウンタイム発生)
書き込みが停止になった後、DBの切り戻しが発生したときのため、移設前DBクラスターに対するレプリケーションを停止し、新たに新クラスターに対するレプリケーションを移設前クラスターで開始する。
そして最後に書き込み用DNS、及び読み込み用DNSを新DBクラスターに向けかえて移設完了となる。(サービス再開)
得られた教訓
- バイナリログを有効化にしたときの性能劣化が激しい
- DBインスタンスのinsertレイテンシーがアクセスピーク時で6倍程度増加した
- サービス稼働中にクラスター間レプリケーションを設定するaws公式の手順が存在しない?
- aws公式手順でのクラスター間レプリケーション設定はサービス停止を前提にした手順であった
- こちらの記事を参考にサービス稼働中でのクラスター間レプリケーション設定をおこなった
- パーティション化による書き込み性能の向上
- レコードがたまり続けていた最後のパーティションを再構成することによって書き込み性能が向上した
まとめ(所感)
今回移設までは事前作業も含めて1週間程費やしたのだが、その中でパーティション再構成にかなりの時間を使った。 リハーサルの段階では13時間程でパーティション再構成できたのだが、レコード数が増えているせいもあってか本番ではなんと2日程かかった。 肥大化しすぎたテーブルに変更を加える際は、ある程度作業時間に余裕を持たせておくことが大切だと改めて感じた。
あとはauroraクラスター間のレプリケーション設定がRDSほど容易ではない点が気になった。 RDS間でのレプリケーション設定は、レプリケーション対象のインスタンスをawsコンソール上から指定するだけでできるが、auroraの場合はsnapshotを復元したり、レプリケーションを手動設定したりなどマニュアルでの手順がかなり多く面倒だった。 いつかクラスター間レプリケーション設定もawsコンソール上からできればうれしいのだが、、、