
2026/07/03 3:38
Postgres トランザクション:分散システムの究極の武器
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
DBOS は、特別な関数
enqueue_workflow を使用してアプリケーションの状態更新とワークフローチェックポイントの記録を単一の原子トランザクション内で実行することにより、標準的な Postgres データベースにワークフローを直接統合する革新的なアプローチを採用しています。この核心となるイノベーションにより、システムは自動的に exactly-once 実行を保証し、開発者が脆弱な重複処理ロジックまたは複雑なリトライメカニズムを手動で実装する必要がなくなります。
従来のシステムでは、状態保存の前にチェックポイントを作成するため、データ損失の危険な WINDOW が発生したり、イベントを確実に同期させるために別の「アウトボックス」テーブルとポーリングプロセスを必要としたりすることがよくあります。DBOS はこの複雑さを完全に回避し、外部エージェンの管理やデータドリフトの調整に伴う大きな運用オーバーヘッドなしでスケーラブルで信頼性のあるアプリケーションを実現します。Postgres ユーザー定義関数を活用してアプリケーショントランザクション内に原子的にワークフロー行を作成することで、開発者はトランザショナルアウトボックスパターンに似た堅牢性を得ながら、インフラストラクチャを単純化できます。その後、ワーカーがこれらのワークフローを非同期で退け(dequeues)して信頼性高く実行します。Postgres 内でネイティブに対応する耐用可能な実行を実装することで、開発者はモダンなイベント駆動アーキテクチャで見られる典型的なインフラストラクチャの肥大化を避けて、単純化されたパフォーマンスを得ることができます。提供されるリソースには、クイックスタートガイド、GitHub リポジトリ、さらなるサポートのための Discord コミュニティが含まれます。
本文
Postgres を同一インスタンスに配置するワークフロー構築のすすめ:アイデムポテンシーとアトミック性の解決策
記事の背景と意図
数週間前、「Postgres をそのまま使えば十分」という記述で長期的なワークフロー(Durable Workflows)の構築について発表いたしました。
- 主な論点: State(状態)を Postgres に保存するだけでは不十分であり、アプリケーションと同一のデータベースインスタンス内にワークフローシステム自体を配置すべきです。
- 誤解への反論: 異なる用途のデータを分離したコンポーネントとして管理するのが一般的ですが、分散システムにおいて**「同じ場所への配置(Co-location)」**は強力な武器となります。
- 利点: ワークフローメタデータとアプリケーションデータを同一の Postgres データベース内に保持することで、両者の更新を一つのデータベーストランザクション内で実行可能です。これにより部分的な失敗を防ぎ、すべてのエッジケースを適切に処理する実装が格段に容易になります。
トランザクショナルなステップによるアイデムポテンシーの解決
分散システムの課題の一つである「アイデムポテンシー(Idempotency:同一的操作に対する結果が一定であること)」の問題について解説します。
課題と一般的な解決策
- チェックポイント問題: ワークフローは中断された場合に最後から再開しますが、ステップの完了記録をチェックポイント書き込みより前に失う場合があり、重複実行のリスクが生じます。
- アプリケーションレベルでの対策: 通常、「ステップ自体をアイデムポテントに設計する」ことを前提とし、追加の追跡処理(bookkeeping)を行います。
- 例:支払い履歴を追跡するための
テーブルを追加し、トランザクション的に更新して重複防止を実現します。applied_payments
- 例:支払い履歴を追跡するための
Co-location によるシンプル化
ワークフロー状態とアプリケーションデータを同一の Postgres データベース内に配置する場合、複雑性が大幅に削減できます。
- 仕組み: チェックポイントの書き込みとデータベース更新を**「同一のトランザクション」**で実行します。
- ワークフローエンジンが提供するデータベーストランザクションを使用してステップを実行。
- ステップ内のデータベース更新を行い、最後にワークフローエンジンがチェックポイントを記録。
- 全体としてアトミック(原子)にコミットされます。
このアプローチにより、データベースとチェックポイントの間に**「窓状態(Window of vulnerability)」**が生じることを排除できます。
- 成功時: データベース更新とチェックポイントは両方永続化され、ステップは二度目には実行されません。
- 失敗時: 更新もチェックポイントもロールバックされ、リカバリ時に最初から安全に実行できます。
その結果、アプリケーションレベルでのアイデムポテンシーロジックや追跡テーブルが不要になり、データベース操作は「正確に一度」「全く実行されない」かのどちらかのみになります(Exactly-once セマンティクス)。
トランザクショナルなワークフローアウトボックスによるアトミック性の解決
複数のシステムへの一貫した更新を行う「アトミック性」の課題についても解説します。
課題と一般的な解決策
- 問題: データベースレコードを更新しつつ、他システムに通知を送る場合など、複数操作がアトミックである必要があります。失敗時にどちらか一方だけ更新されると不整合(データドリフト)が生じます。
- 例:倉庫へ通知せず注文だけ入力される、または存在しない注文について倉庫が通知されるなど。
- 一般的な対策:トランザクショナルなアウトボックス(Transactional Outbox)
- データベースレコードを更新する。
- 同じトランザクション内で「アウトボックステーブル」にメッセージを書き込む。
- バックグラウンドプロセスが定期的にアウトボックスをスキャンし、対象システムへ配信する。
一般的な課題点
- 運用の複雑性: アウトボックスのスキャン、配信、リトライ処理、失敗監視のためのインフラストラクチャが必要になります。
- 分離時のリスク: ワークフローエンジンとデータベースが分離されている場合、状態の不一致を検出するため、下流システムへ通知せずデータベースのみを更新したケースを修正するためのリコンシリアジョンジョブなどの追加インフラが必要となります。
Postgres によるシンプル化ワークフロー
データベースを活用し、ワークフロー状態をアプリケーションデータと同一場所で配置することでパターンを単純化できます。
- 不要になるもの: 手動でアウトボックステーブルを管理したり、別途ポーリングプロセスを持ったりする必要がありません。
- 代替手法:Postgres ユーザー定義関数(UDF)の利用
- アプリケーション更新と同じトランザクション内でワークフローをキューに追加します。
- 例:
という UDF を使用して、ワークフロー行(名称、キュー名、入力値など)を作成。enqueue_workflow
この仕組みにより、アトミック性が保証されます。
- コミット成功: 更新とキューへの追加が同時に完了し、非同期でワーカーがデキューして実行します。
- コミット失敗: どちらも更新されず、後続の処理も発生しません。
これにより、外部システムとの状態不整合を防止しつつ、追加インフラを大幅に削減できます。
さらに詳しく知る
スケーラブルで堅牢なシステムの構築に興味をお持ちでしたら、DBOS の環境を試してみてください。Postgres に裏打ちされた長期的な実行(Durable Execution)をシンプルかつ高性能にするのが目標です。
- クイックスタートガイド: https://docs.dbos.dev/quickstart
- GitHub リポジトリ: https://github.com/dbos-inc
- Discord コミュニティ: https://discord.gg/eMUHrvbu67