ヌーラボブログリレー2024 for Tech Advent Calendar 2024の17日目の記事です。
Backlogのソフトウェアエンジニアの林です。
この記事では、BacklogのAmazon Aurora MySQL 2 → 3移行に伴って行ったAuroraストレージの最適化やその他改善について、その内容を紹介します。
目次
概要
Backlogではサービスを動かすためのRDBとして、Amazon Aurora MySQL を使用しています。
密着 24時! MySQL 5.1 から Aurora への移行100日間 〜 Backlog 編
このBacklogで使用しているAuroraのメジャーバージョンについて近頃ブルーグリーンデプロイにより2系から3系へのアップデートを行ったのですが、その際に長時間のテーブルロックを伴うAuroraストレージ最適化を同時に行いました。
背景
縮小したくてもできない膨大なAuroraストレージ容量
Backlogにはファイルを添付できるいくつかの機能があります。これらは2024年現在においてはS3などにすべてファイル実体があるものの、一部機能はかつて歴史的経緯によりDBにバイナリを持っていたことがありました。
DB保持を廃止しバイナリをS3などに集約する対応が以前行われた際には当然DBのバイナリをクリアしたのですが、Auroraのストレージ自動スケーリングはdeleteやupdateでは領域が開放されず、テーブルをtruncateやforce alterをしないと縮小しないという特性(※1)があります。この制約により、もはや全く使用していない領域が多分に含まれるAuroraストレージの料金を払い続けなければならない状態になっていました。
MySQL5.7からはforce alterであってもオンラインDDL(※2)が使えるものの、MySQL5.6以降に新設もしくは再作成されたテーブルでないと適用されないため、それよりずっと前から運用されているBacklogでこの容量を削減するにはどうあがいても数時間〜数日にわたるテーブルロックを許容する必要があります。これはSaaSの通常運用の中でやるにはなかなかに厳しい制約です。またこのオンラインDDLが使用できない問題はadd indexのalter tableなども同じでして、この制約によりインデックス追加をカジュアルに検討できるテーブルがごく一部に限られているという別の問題も含まれています。
Aurora2 (MyAQL5.7互換) のEOL対応
BacklogでRDBとして使用しているAurora2 MySQLのEOLが2024/11に迫っており、Aurora3 (MyAQL8.0互換)への移行が必要となっていました。AWSからマネージドなブルーグリーンデプロイが提供されており、公式ではメリットが多いこの移行手法が推奨されているのですが、Backlogではアーキテクチャの都合上享受ができないメリット(機能)や、無視できない制約等があり、代替手段として
- アプリの再起動は行い、サービスとしては停止メンテとする
- (ブルーグリーンデプロイも裏側で行っている)バイナリログによるクラスタ間レプリケーションをマニュアルに構築し、実際のアップデートはin-placeとする
といった移行方法を採用しました。(便宜上以下、ブルー・グリーンといった呼称を用いますが、一般名詞としての扱いでありAWS提供のマネージドな移行手法とは関係がないことをご留意ください。)
発案・計画
バイナリログの特性を利用
バイナリログによってクラスタ間レプリケーションを行うため、グリーン側で自動取り込みされる書き込みログとの間に矛盾が発生しない範囲においては下記のような操作をブルーはそのままにグリーンに対してのみでも適用可能です。
- テーブルの再作成(optimize table)
- インデックス作成
かねてよりAuroraストレージ料金の削減を行いたいと考えていたBacklogです。今回私達のチームが担当するAurora3移行に伴うブルーグリーンデプロイ(手動)は好機だと考え、DBアップデート作業の裏側でグリーン環境に対してバイナリの残骸が残るテーブルのoptimizeを行うことにしました。また背景のセクションで触れたとおり今後のインデックス追加をするうえで障壁を除去するという意味で、バイナリを含まない他のテーブルも多くoptimize対象に含める形で計画を立てました。
メンテナンススケジュール
optimizeには非常に時間がかかるため、今回のアップデートではグリーン環境の立ち上げができたら動作確認したのち速やかにブルーから切り替え…というわけにはいきません。グリーンがoptimizeにより実質ブロックされている期間を考慮したうえで停止メンテとグリーン環境立ち上げのタイミングを計画する必要があります。またBacklogでは複数の運用環境があり分かれていることにより障害の局限化や収容ユーザーの調整を図っているため、各環境に対する対応の時期をバラすことができるとベストです。上記を加味してスケジュールを策定しました。詳細は割愛しますが、下記のようなスケジュール感です。土曜に停止メンテを行い、その裏で別環境の最適化のスクリプトが休日の間実行され続けるような流れになります。週明けにスクリプトの完了を確認してアップデートとレプリケーションを行います。
やってみた結果
テーブルのoptimizeにかかった時間
上図で「環境X Optimize」と書かれた箇所のみの所要時間です。土曜日の切り替えのための停止メンテの時間等は含みません。
- 最もOptimizeの時間が長かった環境 … 2 日 10 時間 12 分
- 最もOptimizeの時間が短かった環境 … 26分
- 全環境合計(8環境) … 8日 21 時間 48分
全体的にAuroraストレージの容量とOptimize所要時間との間には緩い比例関係が見られましたが、最も時間がかかった環境は
- 最もレコード数が多く
- データ量は8環境中2番目に大きい環境
となりました。データ量のみならずデータ件数も少なからず関係してくるようです。
削減容量(概算)
VolumeBytesUsed 全環境合計 … 89.2TB => 16.5TB
削減費用
詳細をここに書くことはできませんが、クラスタストレージだけでUSD 0.12/GB/月の単価で73TBの削減(=>約$8,900/月)ができ、さらにバックアップのストレージもUSD 0.023/GB/月とインスタンスのストレージに比べると少ないですが世代数が多いとそれなりのが額がかかっていたのがクラスタストレージと同等の減少量であったため、総費用としてもかなりの削減となりました。
ついでにやったこと
直近でスロークエリが観測されている一部のテーブルカラムにインデックス追加
optimizeの後のalter tableでありしたがってオンラインDDLが利用可能になるのでそういう意味では後日対応でもいいのですが、
- サービス無停止でのオンラインDDLでもメタデータロックにより当該テーブルへのアクセス瞬断がありえるので、グリーン環境に対して実施できる今のチャンスでやるのは悪くない
- 処理の所要時間や対応工数を勘案すると今回の対応スコープに混ぜ込んでもリスクは大差ないとチームで判断した
といった理由から実施しました。とは言うもののオンラインDDLにより今後かなりの局面で無停止を選択できるようになるので、MySQLの進化はありがたいなと思います。
得られた成果としては、数万件の課題を擁するプロジェクトのプロジェクトホームで場合によって数十秒ほど描画にかかるケースがあったところ、長くても数秒程度に短縮することができました。
インスタンスタイプの世代を変更
同一サイズでr5→r6gやr7gに変更しました。グリーン環境をGravitonインスタンスにて立ち上げた後に切り替える形になります。データ,クエリの状況や着目する指標にもよりますが、AASだと10〜20%程度の改善が見られました。
感想
今回のアップデートでは単にバージョンを上げるのみならず、その中でロック・ストレージなどの制約を縫いながらいくつかの改善を行うことでチームやBacklog全体としても多くのナレッジ蓄積ができました。今後も技術的負債の解消を含む様々な改善を実施し、ユーザーにとって使いやすいBacklogを作っていきたいと思います。
※1 なおinsert等データ追加においてはパフォーマンスに影響を与えず無条件に拡張されます
※2 バックグラウンドで暗黙的にコピーが作成され、目的の処理がコピーに対して適用完了するまでは更新がダブルライトされる仕組み。ALTERでもテーブルロックがかからず、懸念点は主に新旧スイッチング時のメタデータロックとI/O増加のみに絞られるため無停止メンテナンスが検討可能になります。