🌊

サービスを止めずに容量問題を解決──DB分離アーキテクチャで実現した段階的アーカイブ移行

に公開

はじめに

こんにちは。スマサテで開発を担当している大場です。社内エンジニアでは古株で、少人数の頃はサーバー構築・開発・保守・エラー対応・デプロイと広い守備範囲をカバーしていました。ここ数年で優秀な仲間が増え、さまざまな課題を分担できるようになりました。今回は、増え続ける顧客データをどのようにアーカイブ化していったか、その取り組みについて紹介します。

課題

弊社のプロダクトには賃貸物件の賃料査定機能があり、2024年に顧客データを保存する機能をリリースしました。査定賃料の算出に必要な賃貸物件の情報は定期的に収集・更新されますが、査定時点の情報をスナップショットとして保持できるようになりました。つまり、賃料とその算出に使った関連データを一式保存する仕組みです。1つの賃料査定で複数テーブルに関連レコードが合計数千行生成されます。
ありがたいことに査定件数は増え続けていますが、これに伴いDB容量の課題に直面することになりました。

データ削除の検討と方針決定

特定の期間での査定結果の閲覧頻度を分析したところ、査定当日から30日経過時点までの査定結果で全閲覧回数の97%を占めることがわかりました。
そこで容量削減のため、1年以上経過したレコードの削除について営業チームと相談しました。しかし、過去の査定を振り返るお客様の利用シーンや、顧客志向という弊社方針から、すべてのデータを保持し続けることが決定しました。

事前の検証と対策の決定

古いデータの退避と現行DB容量の削減が目的です。検証環境でダミーデータを投入し、速度やカラム追加などへの影響を検証したところ、大きな問題は見つかりませんでした。
とはいえ、データが膨大になりすぎて予期せぬ弊害が起こる前に対策を講じるべきと判断し、CTOを含めた議論で実行を決定しました。

実現に向けた案

圧縮
容量が大きいテーブルをMySQLの ROWFORMAT=COMPRESSION で圧縮します。事前にテストを実施し、速度低下がないことを確認したうえで本番に適用しました。今回のケースではデータは元のサイズの34%程度まで圧縮できました。速度低下が誤差程度であったことに対してストレージ使用量がこれだけ削減できるので十分なメリットがあります。

なお、 ROWFORMAT=COMPRESSION を指定すると列追加の際に ALGORITHM=INSTANT が指定できず( INPLACE は場合により指定可能)、列追加に時間がかかります。頻繁に列変更が必要な場合はその点考慮したほうがよいでしょう。

テキストに書き出し、圧縮後にS3保存
理論上は可能ですが、プログラムの修正工数が大きいことに加え、現行テーブルへのカラム追加時に圧縮データが追従できないのも致命的です。この案は見送りました。

スマサテアプリ内でDB分離
実装は一番簡単です。アーカイブDBを用意し、スマサテDBとアーカイブDBでデータを行き来するロジックを作るだけで実現できます。ただし、大量データのアーカイブ・復元時にサーバーのCPU、メモリ負荷が懸念されることや、開発環境の複雑化を考慮し、次の案を採用しました。

新サーバーを用意し、スマサテDBとアーカイブDBを管理(採用案)
データのアーカイブと復元だけを司る新サーバーを立ち上げます。夜間バッチで一定期間を過ぎた査定データをアーカイブDBに移行し、元のデータを削除。復元はAPIで実装します。

新サーバー稼働で得られるメリット

  1. 既存のスマサテサーバーに負荷を与えない
  2. 復元APIのみをスマサテアプリケーションに実装すればよい(他のエンジニアはアーカイブロジックを意識する必要がない)
  3. 他DBで容量問題に直面した際、同じスキームを再利用できる

効果

最初に行った容量圧縮で30%削減し、残り70%の3分の2をアーカイブ化しました。お客様のユーザー体験を変えることなく、データを損なうこともなく、最終的に70%以上の容量削減を実現できました。

エラー対応

リリース後、いくつかの問題が発生しました。

Waiting for table metadata lock

データ移行に失敗し、スマサテサーバー・アーカイブサーバー両方にデータが残りました。原因は、移行したレコードのIDをRuby側で配列化し、WHERE id IN (...)のクエリを複数テーブルに対して順番に発行していたためです。SQL文の長大化により、生成された実行計画では子テーブルを逐次ロックし続ける形になっていました。この箇所をサブクエリ化することで解決しました。

おわりに

増え続ける顧客データの保持と、DB容量削減という相反する要求に対して、アーカイブサーバーを用いたDB分離アーキテクチャで対応しました。データ圧縮とアーカイブ化により70%以上の容量削減を実現し、お客様のユーザー体験を損なうことなく、すべてのデータを保持し続けることができました。段階的な移行とエラー対応を経て、他のDBでも活用できる汎用的なアーカイブ基盤を構築できたと考えています。

スマサテでは、このような技術的課題へ一緒に取り組んでくれるエンジニアを募集しています。インフラからアプリケーションまで幅広い領域で挑戦したいという方は、ぜひWantedlyをご覧ください。

https://www.wantedly.com/projects/2099580

スマサテ Tech Blog

Discussion