Slide 1

Slide 1 text

2時間かかる月次バッチを 10分に短縮した スケーラブルな バッチアーキテクチャ改善 金森 秀平(プラットフォームエンジニアリング1G) @_MoneyForest

Slide 2

Slide 2 text

自己紹介

Slide 3

Slide 3 text

自己紹介 金森 秀平(@_MoneyForest) - 所属: タイミー プラットフォームエンジ ニアリングチーム 1G - うさぎ(7歳♂)を育ててます - SIer -> Backend -> SRE

Slide 4

Slide 4 text

🔍 2時間かかる月次バッチを10分に短縮した事例についてお話しします 🔍 前半で月次バッチが抱える問題を紹介し、後半でその改善アプローチについてお話 しします はじめに

Slide 5

Slide 5 text

1 月次バッチの概要

Slide 6

Slide 6 text

🔍 月初めに起動する 🔍 月次バッチの完了後、お客様に対して手動での後工程が存在する 🔍 2時間以内には月次バッチの全プロセスを完了させておく必要がある 🔍 月次バッチが遅延してしまうと、お客様の事務処理にご迷惑をおかけしてしまう恐 れがある 月次バッチの制約

Slide 7

Slide 7 text

🔍 対象の「企業」をデータベースから取得し、ループで処理する 🔍 内部的には複数のDBテーブルに対して、指定のバッチサイズごとに Read した後 に、パラメータを整形して Bulk Insert, Update をしている(レコード数は100~200万くら い) 🔍 単発のジョブで実行されており、失敗するとロールバックのジョブを流してから再リラ ンする必要がある 🔍 CPUよりも、DBのI/Oが支配的である 月次バッチの処理とボトルネック

Slide 8

Slide 8 text

2 月次バッチが 直面する問題

Slide 9

Slide 9 text

線形に増えるデータ量 2026年1月以降はいつ処理時間が2時間を超えてもおかしくない状況に 2025/04/01時点での処理時間予測グラフ 🔍既に2時間を超えていたこともある 😇 🔍年末は稼働数が多いので、 2時間を超 えてもおかしくない 😇 🔍来年5月からは定常的に 2時間を超える 😇

Slide 10

Slide 10 text

タイミングをずらすことも難しい 🔍 月次バッチの大量データは月末で確定する 🔍 月末で確定したのち、速やかに計算する必要がある 🔍 お客様への業務プロセスにも影響するため、ずらすことが難しい

Slide 11

Slide 11 text

じゃあどうするか? 抜本的に処理を改善 するしかない

Slide 12

Slide 12 text

3 月次バッチの抜本改善

Slide 13

Slide 13 text

🔍 各処理は企業単位でループして いるため、企業単位で並列化するア プローチを検討 改善アプローチ

Slide 14

Slide 14 text

1. データの依存関係を分析 2. トランザクション境界の判断 3. 運用設計で安全性を担保 4. 非同期処理アーキテクチャの適用 改善手順

Slide 15

Slide 15 text

データの依存関係を分析(スキーマ・モデル構造) 🔍 作成、更新するテーブルはすべて企業 をルートとして辿れることを確認 ✅ 企業単位での集約が可能で、ロジック が集約の中に閉じている可能性

Slide 16

Slide 16 text

データの依存関係を分析(副作用の確認) 🔍 処理について企業の 集約同士でそれぞれの集 約への副作用が発生しな いことを確認 ✅ 並列化によりロックの 競合が発生しない ✅ 並列化により不整合 データを作ってしまう恐れ がない

Slide 17

Slide 17 text

🔍 ここまでで「企業の集約単位でビジネスロジックが独立している」ことを確認 ✅ 企業の集約単位で1つのトランザクションにすることができる ✅ トランザクションのACID原則により、ビジネスロジック単位の整合性を保証できる トランザクション境界の判断 ただし問題が・・・

Slide 18

Slide 18 text

❌ ロックによる他の処理のブロック ● 大企業1社で大量のレコード → 処理時間: 10分程度 ● 10分レコードロックがかかるのは他処理との兼ね合いで許容できない ● 時限までに正しい結果が揃っていればいい(結果整合性を許容できる) 企業単位トランザクションの評価 企業の集約単位でトランザクションを張らない判断 ACID原則による整合性が保証できなくなるため 運用設計で安全性を担保する必要がある

Slide 19

Slide 19 text

✅ 自動リトライの無効化 & 厳密なエラーハンドリング ● 不確実な自動リトライで状況を悪化させない ● エラー箇所によって異なるリカバリオペレーションが必要 運用設計で安全性を担保

Slide 20

Slide 20 text

✅ Runbook(障害対応手順書)の整備 ● 想定可能な障害パターン別のリカバリ手順を用意 ● ログベースアラートで、エラー種別ごとに異なるRunbookを添付するようなアラート および手順の整備 ✅ ロジックによる冪等性の確保 ● リカバリ手順をシンプルにするため再実行時に重複レコードが作られないようなハ ンドリング ● すでに処理済みのステップはスキップ 運用設計で安全性を担保

Slide 21

Slide 21 text

● 既存資産のSidekiqを活用した非同期処理アーキテクチャを構築 非同期処理アーキテクチャの適用

Slide 22

Slide 22 text

● パフォーマンス :ECSタスク台数分の並列度で処理できる ● スケーラビリティ :企業が増えても、ECSのタスク台数を増やすことで、処理時間の 増加を抑制できる ● 耐障害性:個別の企業(ジョブ)でエラーが発生しても、他の企業の処理には影響 せず、失敗したジョブのみを個別にリトライ可能 (前は1件でも発生すると即障害) ● 負荷軽減:Sidekiqのジョブキューを分離し、さらに既存Sidekiqとは別のECSサー ビスに切り出し、他のジョブに影響しない/されないように 非同期処理アーキテクチャのメリット

Slide 23

Slide 23 text

4 学び

Slide 24

Slide 24 text

● 「並列化の単位」と「トランザクションを張るか」は別の判断 ○ 並列化: ドメインの境界(企業単位) ○ トランザクション: 非機能要件(企業単位では張らない) ● トランザクションを張るかの判断基準 ○ ロック競合の影響(最重要) ○ データ整合性の要求レベル(要件的に結果整合性を許容できる) ● DBトランザクションを諦める選択肢 ○ ACID特性を諦める → 運用設計で安全性担保 ○ ロジックによる冪等性担保 + 手動リカバリ + モニタリングでカバー 学び

Slide 25

Slide 25 text

ご清聴ありがとうございました!