Upgrade to Pro — share decks privately, control downloads, hide ads and more …

データの整合性を保つ非同期処理アーキテクチャパターン / Async Architecture...

mokuo
February 13, 2025

データの整合性を保つ非同期処理アーキテクチャパターン / Async Architecture Patterns

Developers Summit 2025 公募セッション "データの整合性を保つ非同期処理アーキテクチャパターン"
https://event.shoeisha.jp/devsumi/20250213/session/5585
---

1つの業務が一連のイベント(出来事)から構成されるシステムというものがあります。非同期処理を含むこともあるでしょう。
このような機能を開発・運用していると、以下のような課題に直面することがあります。

・処理の流れが把握し辛い
・変更を行うのが困難
・データの整合性を担保するのが難しい

しかし、適切に設計を行うことで、これらの課題を回避することができます。
本セッションでは、弊社が運営する B/43 アプリのカード発行フローなどを例に、上記の課題を解消するアーキテクチャのパターンを紹介します。

mokuo

February 13, 2025
Tweet

More Decks by mokuo

Other Decks in Programming

Transcript

  1. 3 SmartBank, Inc. 
 Engineer 
 木田 悠一郎
 @mokuo_
 @mokuo


    SIer : 基幹業務システム → Rails 受託開発
 → Sansan株式会社 : データを扱う部署で複数システム
 → 株式会社スマートバンク : カード決済 / あとばらい領域

  2. 4

  3. 5

  4. 6 6

  5. 7 7

  6. イベントを正しく保存する
 • イベント
 ◦ 日付を生成条件としているモノ 
 • リソース
 ◦ イベント以外のモノ


    モノを2種類に分ける
 15 出典: 事業分析・データ設計のためのモデル作成技術入門:書籍案内|技術評論社 https://gihyo.jp/book/2022/978-4-297-12946-0

  7. 16 イベントを正しく保存する
 • 出来事の結果として生起した、持続するモノに帰属している日付
 ◦ ❌ 従業員入社日、部門設立日など
 • データ管理のための将来日
 ◦

    ❌ 有効日、適用日など
 • データ管理のための過去日
 ◦ ❌ 登録日、更新日など
 イベントに帰属する日付は事象が生起した過去日
 ※ 以下はイベントの日付ではない
 = 受注日、発送日、請求日、入金日 など

  8. • 👍 メリット
 ◦ イベントの順序が明確になり、外部キー制約などを活用できる
 • 👎 デメリット 
 ◦

    イベントの関連を1つずつ辿っていく必要がある
 パターン① : 1つ前のイベントのIDを持つ
 19 イベントを正しく保存する

  9. パターン② : 最初のイベントのIDを持つ
 21 • 👍 メリット
 ◦ イベント分岐に対応できる、関連イベントを一気に引ける
 •

    👎 デメリット 
 ◦ イベントの順序をテーブルだけで表現できない
 イベントを正しく保存する

  10. パターン③ : ロングタームイベント
 23 最新のステータス 
 各イベントのスーパータイプ 
 • 👍

    メリット
 ◦ 最新のステータスを管理できる、複雑なイベント分岐に対応可能
 • 👎 デメリット 
 ◦ テーブルだけでイベント順序を表現できない
 イベントを正しく保存する

  11. 『WEB+DB PRESS Vol.130』の特集1
 第4章で紹介されているパターン
 パターン③ : 
 ロングタームイベント
 出典: WEB+DB

    PRESS Vol.130|技術評論社 https://gihyo.jp/magazine/wdpress/archive/2022/vol130
 24 イベントを正しく保存する

  12. • 👍 メリット
 ◦ 関連するイベントを柔軟に引くことができる
 • 👎 デメリット 
 ◦

    ライブラリがない言語では実装にコストがかかる
 Ruby では ancestry という gem があり
 簡単に導入することができる
 出典: stefankroes/ancestry: Organise ActiveRecord model into a tree structure https://github.com/stefankroes/ancestry
 26 パターン④ : 
 ツリー構造で持つ
 イベントを正しく保存する

  13. 書籍『SQL アンチパターン』で 経路列挙モデル として紹介されている手法
 パターン④ : 
 ツリー構造で持つ
 27 出典:

    SQLアンチパターン - O'Reilly Japan https://www.oreilly.co.jp/books/9784873115894/
 イベントを正しく保存する

  14.    関連するイベントの数や複雑さに応じて、
 
 
 
   の順に検討してみる!
 パターンまとめ
 28 パターン① : 1つ前のイベントのIDを持たせる


    パターン② : 最初のイベントのIDを持たせる
 パターン③ : ロングタームイベント
 要件によって 
 ”パターン④:ツリー構造で持たせる”パターンも検討すると良い
 イベントを正しく保存する

  15. 複数の責務、概念が混ざり合っている
 
 null カラムが生じる
 イベントを正しく保存する
 NGパターン: 全部盛りモデル
 29 カード発行
 PK


    ID
 ユーザーID
 カードID
 ステータス
 カード名義
 配送先
 申請日時
 発行日時
 発送日時
 利用開始日時

  16. 「可用性」 の定義
 
 ” システムがどれくらいの期間利用できるか 
 (24 時間 365 日稼働する場合には、障害が発

    生した場合に迅速にシステムを稼働できるよう にするための措置が必要となる) ”
 
 出典:ソフトウェアアーキテクチャの基礎 - O'Reilly Japan https://www.oreilly.co.jp//books/9784873119823/
 36 イベント間の整合性を保つ

  17. 42 裏側で非同期通信を行うことで、
 パフォーマンス と可用性が向上する
 
 カード管理
 システム
 アプリ
 バックエンド
 家計簿


    アプリ
 非同期通信の場合
 非同期
 ⚠ ただし、デメリット もある
 イベント間の整合性を保つ

  18. 43 DBトランザクションの
 ACID 特性
 • 原子性(Atomicity)
 ◦ 全て成功 or 失敗


    • 一貫性(Consistency)
 ◦ 全ての制約が満たされた状態
 • 独立性(Isolation)
 ◦ 直列に実行した場合と結果が同じ
 • 耐久性(Durability)
 ◦ コミット完了したデータが消失しない
 出典:理論から学ぶデータベース実践入門 ―― リレーショナルモデルによる効率的な SQL|技術評論社 https://gihyo.jp/book/2015/978-4-7741-7197-5
 
 イベント間の整合性を保つ

  19. ç ç ç 45 リトライ
 最初から
 実行し直す 
 ロールバック 


    (もとに戻す)
 非同期処理に失敗した時、以下のいずれかの対応を行う必要がある
 イベント間の整合性を保つ

  20. 46 イベント間の整合性を保つ
 出典:Saga パターン - Azure Design Patterns | Microsoft

    Learn https://learn.microsoft.com/ja-jp/azure/architecture/patterns/saga
 • コレオグラフィ
 • オーケストレーション
 整合性担保のための2つのアプローチ
 マイクロサービス における概念だが、モノリスでも参考にできる

  21. 47 • 👍 メリット
 ◦ 調整ロジックが不要
 ◦ 単純なフローに適している
 • 👎

    デメリット 
 ◦ ステップが増えると複雑になる
 コレオグラフィ
 イベント間の整合性を保つ
 出典:Saga パターン - Azure Design Patterns | Microsoft Learn https://learn.microsoft.com/ja-jp/azure/architecture/patterns/saga

  22. 48 オーケストレーション
 イベント間の整合性を保つ
 出典:Saga パターン - Azure Design Patterns |

    Microsoft Learn https://learn.microsoft.com/ja-jp/azure/architecture/patterns/saga
 • 👍 メリット
 ◦ 全体を管理しやすい
 ◦ 複雑なフローに適している
 • 👎 デメリット 
 ◦ オーケストレーターにロジックが集中する

  23. 49 オーケストレーション
 イベント間の整合性を保つ
 出典:Saga パターン - Azure Design Patterns |

    Microsoft Learn https://learn.microsoft.com/ja-jp/azure/architecture/patterns/saga
 オーケストレーターとして
 マネージドサービスを導入する
 • AWS
 ◦ AWS Step Functions
 • GCP
 ◦ Workflows
 • Azure
 ◦ Azure Logic Apps

  24. 50 オーケストレーション
 イベント間の整合性を保つ
 出典 : chaps-io/gush: Fast and distributed workflow

    runner using ActiveJob and Redis https://github.com/chaps-io/gush
 ちなみに・・・
 Ruby には gush という gem があり、
 Redis か ActiveJob を使ってワークフローを組 むことができる

  25. オーケストレーターとして使えるマネージドサービス
 53 例) AWS Step Functions
 • どこでエラーになったか分かる
 • リトライやエラーハンドリング

    可能
  ※ 右図はイメージです
   実際の B/43 カード発行フローとは異なるためご注意ください

  26. 55 DBトランザクションの
 ACID 特性
 • 原子性(Atomicity)
 ◦ 全て成功 or 失敗


    • 一貫性(Consistency)
 ◦ 全ての制約が満たされた状態
 • 独立性(Isolation)
 ◦ 直列に実行した場合と結果が同じ
 • 耐久性(Durability)
 ◦ コミット完了したデータが消失しない
 出典:理論から学ぶデータベース実践入門 ―― リレーショナルモデルによる効率的な SQL|技術評論社 https://gihyo.jp/book/2015/978-4-7741-7197-5
 
 データベースとメッセージキューの整合性を保つ

  27. 56 DB にデータを保存しつつ
 メッセージを送信したいことがある
 
 カード管理
 システム
 アプリ
 バックエンド
 家計簿


    アプリ
 非同期通信の場合
 非同期
 データベースとメッセージキューの整合性を保つ

  28. データベースとメッセージキューの整合性を保つ
 出典: マイクロサービスパターン 実践的システムデザインのためのコード解説 - インプレスブックス
 https://book.impress.co.jp/books/1118101063
 61 “ データベーストランザクションの一部として

    データベースの OUTBOX テーブルにイベン トやメッセージを保存することによってメッ セージをパブリッシュする “ (https://microservices.io/patterns/data/transactional- outbox.html 参照)
 Transactional outbox
 パターン

  29. 62 OUTBOX テーブルを読み、メッセージ をパブリッシュする方法として、さらに2 つのパターンがある Transactional outbox
 パターン
 データベースとメッセージキューの整合性を保つ
 出典:

    マイクロサービスパターン 実践的システムデザインのためのコード解説 - インプレスブックス
 https://book.impress.co.jp/books/1118101063

  30. ワーカー常時起動、バッチ定期実行など
 63 “ データベースの OUTBOX テーブルを ポーリングしてメッセージをパブリッシュす る ” (https://microservices.io/patterns/data/polling-pub

    lisher.html 参照)
 パターン① : 
 Polling publisher
 OUTBOX テーブルからメッセージをパブリッシュする方法
 出典: マイクロサービスパターン 実践的システムデザインのためのコード解説 - インプレスブックス
 https://book.impress.co.jp/books/1118101063

  31. 64 “ トランザクションのログをテーリングして データベースに加えられた変更をパブリッ シュする ” (https://microservices.io/patterns/data/transaction -log-tailing.html 参照)
 パターン②

    : 
 Transaction log tailing
 出典: マイクロサービスパターン 実践的システムデザインのためのコード解説 - インプレスブックス
 https://book.impress.co.jp/books/1118101063
 例) MySQL の binlog、
   PostgresQL の WAL など
 OUTBOX テーブルからメッセージをパブリッシュする方法

  32. 65 出典: マイクロサービスパターン 実践的システムデザインのためのコード解説 - インプレスブックス
 https://book.impress.co.jp/books/1118101063
 いくつかの例が書籍で紹介されている
 • Debezium

    / Eventuate Tram
 ◦ DB への変更を Apache Kafka にパブ リッシュ
 • LinkedIn Databus
 ◦ Oracle トランザクションログ
 • DynamoDB streams
 OUTBOX テーブルからメッセージをパブリッシュする方法
 パターン② : 
 Transaction log tailing

  33. 66 補足: 重複するメッセージの処理
 例) Amazon SQS
 出典 : サーバーレスにおけるべき等性の実装 (メッセージ編)|

    AWS 
 https://aws.amazon.com/jp/builders-flash/202106/serverless-idempotency-implementation/
 • 標準キュー 
 ◦ At-Least-Once Delivery
 • FIFOキュー
 ◦ Exactly-Once-Processing
 どちらのタイプでもメッセージ削除に 失敗す ると複数回処理されることがある

  34. メッセージのスキーマを定義する
 https://json-schema.org/tools から 探すことができる
 例えば Ruby には json-schema とい う

    gem ライブラリがある
 (https://github.com/voxpupuli/json-schema 参照)
 71 JSON Schema バリデーター