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

イベントの整合性をどう保つか - Sekiban.DCBのアプローチ

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

イベントの整合性をどう保つか - Sekiban.DCBのアプローチ

イベントソーシング・CQRS 勉強会 #5
https://sekiban.connpass.com/event/380134/

株式会社ジェイテックジャパン
Developer Advocate for Sekiban 川江貴志

イベントソーシングを実践する際、幾つかの課題を克服する必要があります。そのうちの一つが、イベントの整合性をどのように保つか、という問題です。このセッションでは、本来の DCB と Sekiban.DCB がそれぞれ、この問題にどのようにアプローチしているか、比較して解説します。

Avatar for Takashi Kawae

Takashi Kawae

February 12, 2026
Tweet

More Decks by Takashi Kawae

Other Decks in Programming

Transcript

  1. 集約ごとの整合性 ❖ 集約ごとにイベントストリームを持つ ❖ 集約という境界内の整合性を、楽観的同時実 ⾏制御によって守ることが⼀般的 ❖ 処理の競合を避けるために、イベントスト リームの現在のバージョンが⾃分の期待する ものと⼀致するかどうか判定する

    ❖ 各集約のストリームごとのバージョンチェッ クは⽐較的実装しやすい 集約をまたぐ場合の整合性 ❖ 複数の集約にまたがる制約の強制が困難 ❖ 例えば「コースの定員を超えてはならない」 と「学⽣は10科⽬以上登録できない」という 2つの制約を同時に満たす必要がある場合、 コースと学⽣はそれぞれ別の集約であるた め、単⼀のトランザクションでは両⽅の制約 を検証できない ❖ Saga による調整が必要になるが、複雑さの 増加と副作⽤を伴う ⼀般的なイベントソーシング
  2. • イベントを集約に紐づける代わりに、 タグを付与する • ⼀つのイベントに複数のタグを付与可能 • 概念上、集約単位ではなく、境界付けられたコン テキスト全体で⼀つのイベントストリームを持つ • ⼀つの事実を複数の集約ストリームに分けて書き

    込まないため、整合性保持のための多段処理 (Saga) を減らせる • ⼀貫性境界はコマンドごとに、読み取りクエリと して動的に定義される https://dcb.events/ Dynamic Consistency Boundary (DCB)
  3. Query Definition イベントタイプやタグを組み合わ せた「クエリ」で⼀貫性の境界を 定義 Global Sequence 集約のストリームごとのバージョ ン番号ではなく、グローバルな シーケンスポジションを使⽤

    Append Condition 「指定ポジション以降に、クエリ にマッチするイベントが存在しな い」ことを条件に書き込む Append Condition による DCB の楽観的ロック
  4. Read & Record クエリによって Decision Model を構築、 Decision Model 構築時点で

    クライアントが把握していた 最⾼のシーケンスポジションを 記録 Decision ビジネスロジックを実⾏し、 新しいイベントを⽣成するか 判断 Append Condition イベント書き込み時に 「記録したポジションより後で クエリにマッチする イベントの追記がないこと」 を条件に指定 Commit/Reject 条件が満たされれば アトミックに書き込み、 満たされなければ競合とみなし 書き込みは⾏わない DCB のコマンド実⾏フロー
  5. 1. 条件付き書き込み対応 ❖ クエリによる検証とイベント追記を不可分 (アトミック)に⾏うため、データストアに Append Condition に対応できる機能が要る ❖ 全イベントに対してグローバルなSequence

    Positionを付け、且つクエリで正確に絞り込 める必要があり、データストアの物理分割‧ 分散と両⽴させるのが難しい ❖ 任意のクエリ組み合わせでの抽出+条件付き 書き込みを⾼性能に実現するのが難しい 2. 複数ストレージ対応 ❖ DCB に必要な機能はストレージに依存する ❖ 整合性保証の仕組みの実装がストレージごと に必要になり得る DCB の楽観的ロックを実装する上での技術的ハードル
  6. • OSS の イベントソーシング / CQRS ⽤フレームワーク • Sekiban の幾つかのバリエーションのうち最も新しい

    ◦ 現在アクティブに開発されている • イベントを複数タグに紐づけられる ◦ 純粋な DCB 準拠ではない(後述) • Microsoft Orleans をアクターモデル⽤の フレームワークとして使⽤ https://github.com/J-Tech-Japan/Sekiban Sekiban.DCB
  7. Microsoft Orleans Orleans の概要 ❖ 分散アプリケーション構築のための アクターモデルに基づくフレームワーク ❖ オープンソースプロジェクト https://github.com/dotnet/orleans

    ❖ 仮想アクター (Virtual Actor) を採⽤ Orleans の仮想アクター ❖ アクターの⽣存管理が⾃動化されているため、 開発者がアクターの⽣成と破棄を明⽰的に管理する 必要がない ❖ アクセスされた時に⾃動的に活性化(メモリ上に⽣ 成)され、⼀定時間アクセスがなければ⾃動的に ⾮活性化(メモリから解放)される ❖ アクターを⼀意な論理 ID で呼び出せるので、クラス ター内のどこに存在しているか意識する必要がない ❖ 同⼀ ID のアクターはクラスター全体で原則1つだけ (障害時等、⼀時的な重複はあり得る)
  8. 1 Actor per Tag “1つのアクターが⼀度に1つのメッセージだけ処理する” “同⼀ ID のアクターはクラスター全体で1つだけ存在” Sekiban.DCB はアクターのこれらの性質を同時実⾏制御に使⽤

    • タグ1つにつきアクター1つを配置する • タグの ID をアクターの ID として使う • あるタグに対する操作は、必ず1つの特定のアクターが担当 これによって、 ➔ 同⼀タグへの並⾏処理の同時実⾏制御が可能 ➔ 分散環境でも単⼀プロセスのような安全な処理が可能 ➔ 多様なストレージに対応しやすくなる Orleans アクターによる同時実⾏制御
  9. アクター+バージョンチェック ❖ イベントに付される ID ❖ イベントストリームの中でグローバルに⼀意 ❖ ⽣成時間順にソート可能 ❖ タグは、⾃分に影響を与えた最後の

    SortableUniqueId を管理している ❖ イベントストリームにおけるイベントの位置 情報としての役割と、タグのバージョンとし ての役割がある ❖ コマンドは、書き込みたいイベントが影響を与 えるタグの担当アクターに処理の予約を申請 ❖ 担当アクターは以下を判断し、条件を両⽅満た せば予約を許可する 1. 他の予約がすでにあるか? 2. 申請者が前提とする SortableUniqueId は ⾃分の知る最新と⼀致するか? ❖ 予約が取れたコマンドはイベント書き込み後に 担当アクターに確定を通知し、担当アクターは その予約を解放する SortableUniqueId 予約と解放の⼿順
  10. 複数タグへの対応:All-or-Nothing での予約 • Sekiban.DCB で書き込むイベントが複数のタグに 紐づく場合、各タグはそれぞれ独⽴したアクター なので、別々に予約を申請する必要がある • あるタグの予約は成功するが、別のタグの予約は 失敗する可能性がある

    • 影響する全タグの担当アクターに対して並⾏して 予約を申請し、全員から予約を得られた場合のみ イベントの書き込みに進む • ⼀つでも失敗した場合は、成功済みの予約をすべ てキャンセルして中断する
  11. Pure (本来の) DCB Sekiban.DCB アプローチの⽐較 ❖ Append Condition による楽観的ロック (クエリベースの条件付きアトミック追記)

    ❖ ⼀貫性境界:コマンド実⾏時のクエリ ❖ 整合性保証とスケールの可否がデータストア に⼤きく左右される ❖ アクター+バージョンチェックによる 同時実⾏制御 ❖ ⼀貫性境界:タグ(アクター) ❖ 整合性保証とスケールの可否はデータストア にそれほど依存しない ❖ Sekiban.DCB のタグは、⼀般的なイベント ソーシングの集約に近い