Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Spanner Change StreamによるTransactional Outboxでの ...
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Gaudiy Dev
October 14, 2025
0
1
Spanner Change StreamによるTransactional Outboxでの 分散トランザクションの高速化
Go Night Talks – After Conference 11社合同開催!Goエンジニア交流LTイベント
by 雨宮 悟(rail44)
https://x.com/rail44
Gaudiy Dev
October 14, 2025
Tweet
Share
More Decks by Gaudiy Dev
See All by Gaudiy Dev
Connectrpcで始まるContract-first開発
gaudiy_dev
0
1
AI-DLCの思想に基づくこれからのAI駆動開発
gaudiy_dev
0
0
Green Tea Garbage Collector の今
gaudiy_dev
0
0
Automating Web Accessibility Testing with AI Agents
gaudiy_dev
0
0
Featured
See All Featured
My Coaching Mixtape
mlcsv
0
71
XXLCSS - How to scale CSS and keep your sanity
sugarenia
249
1.3M
The browser strikes back
jonoalderson
0
790
Optimising Largest Contentful Paint
csswizardry
37
3.6k
Design in an AI World
tapps
0
170
Balancing Empowerment & Direction
lara
5
940
Digital Ethics as a Driver of Design Innovation
axbom
PRO
1
220
GraphQLの誤解/rethinking-graphql
sonatard
75
11k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
Designing for Timeless Needs
cassininazir
0
160
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
38
2.8k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
1.8k
Transcript
Spanner Change Streamによる Transactional Outboxでの 分散トランザクションの高速化 株式会社 Gaudiy ⾬宮 悟(@rail44)
Profile https://x.com/rail44 https://github.com/rail44 Gaudiyでは主に決済基盤やEC機能の開発をフルスタックに⾏っています 好きな⾔語はRust、好きなエディタはNeovim、好きなOSはVoid Linux
None
None
Goでマイクロサービスをやる - gRPCでBFF/サービス間の通信 - gokitをベースに⾃社独⾃の共通ライブラリをメンテナンス - ドメイン単位でマイクロサービスがk8sに展開 - データベースにはSpannerを採⽤ -
全IPがインスタンスに同居している - IP毎のTenantIDを各テーブルのPKとして持っているので - マルチテナンシーを実現しつつ、⾃然に分散する感じ - インデックスだったり分散のためのキーだったりで普通のRDBMSと差はある - が、今回の話だと割と普通のトランザクショナルなデータベースとして捉えてもら えれば⼤丈夫です - コストは思われている程ではないのと、将来のスケールコストを先払いしているという 理解でいる - 最近だとtidb、Supabaseとか、pgsql本体の進化が強くて個⼈的な気持ちは揺らい でいるが……
マイクロサービスのおさらい Pros - スケールさせやすい - パフォーマンスに問題のあるサービ スを個別でスケールアップ/スケール アウトできる - 影響範囲をチームの単位で切りやす
い - コンウェイ/逆コンウェイ的な - (私たちのような)マルチテナントと の相性がよい - テナント毎に、提供したい機能で必 要なマイクロサービスを組み合わせ る Cons - サービス間通信でのデータの⼀貫性 - 疎結合が故のやつ - gRPCやOpenAPIのようなスキーマ 駆動である程度対策ができる - ランニングコスト - 私たちで⾔えば、スケールに伴うコ ストを先払いしている形 - サービス間で⼀貫したトランザク ションを実現しにくい - ↑これ!
簡単な例 マイクロサービスにぶらさがるSpannerの単位でしか⼀貫性 を持てない
共通DB - ⼈類が幾度も繰り返してきた誤ち - トランザクションがコンテキスト境界を超える - ⼀度構成してしまうと、分離が困難
Sagaパターン - 結果整合性が得られる - 整合性が得られるまでは時間がかかる - 補償トランザクションの設計が複雑 - 外部に失敗の要因がある場合は有⽤
Transactional Outbox - 結果整合性が得られる - やはり、整合性が得られるまでは時間がかかる - pollingが介在する分、sagaよりも時間がかかりやすい - 失敗時のリトライを⾏いやすい
- 「成功する保証が強い」フローとの相性がよい
Saga vs Outbox - アプリケーションの処理フローとして、「失敗しうる」処理かどうか - 外部サービスへの依存の有無 - 処理が失敗した場合のハンドリングをOutboxで⾏おうとするとちょっと⾯倒 -
PubSubのリトライ戦略やデッドレターの設計が必要になる - 「確実に成功させたい」処理 -> Outbox - 「失敗も含め結果整合性を得たい」-> Saga - フローの傾向として、Outboxの⽅がフィットするパターンは多い - アプリケーションの特性にもよるが - アプリ全体としてレジリエンシー重視をする判断 - 補償トランザクションの必要性を減らす - コードやコンポーネントの⾒通しがよくなる 決済システムでは、ステートマシンでSagaっぽく状態管理しつつ、他サービスとの協調はOutboxでやっている(余談)
結果整合性を早く得たい! - pollingが介在するのでサービス間で整合性が得られるのが遅い - だいたい5sec間隔でWHERE SentAt IS NULLを発⾏ - インデックスが効いているとはいえ、頻繁なSELECTを発⾏することは避けたい
- アプリケーションとしてUXを阻害していた - 購⼊した商品が履歴やアイテム⼀覧で確認できるまでに時間がかかる
Spanner Change Stream - https://cloud.google.com/spanner/docs/change-streams?hl=ja - データベース全体や特定のテーブルに対し、指定した変更が発⽣したことを イベントとしてPublishする機能 - タイムスタンプを指定して、それ以降のイベントをストリームで受信できる
- ただし、イベントの保持期間(7⽇)はある - 他のDBでも類似機能はあるはず - CDC、あるいはLISTEN / NOTIFY - 標準ではなくプラグインなら、SupabaseのRealtimeや、ETLはかなり近い
Outbox with Change Stream - チームメンバーが書いた記事 - マイクロサービスの共通ライブラリ(gokit)に、OutboxへのPublishのための コンポーネントを実装 -
ここで記事からコードサンプルを⾒せる - サービスのプロセス内に、Change Streamを購読するgoroutineを起動 - インスタンス間でのAtomic性のために、ロックを取りつつPubSubへPublish
運⽤の上での知⾒ - 結果整合性が得られるまでの時間が5s -> 200msに 🎉 - イベント単位での再送機構はない - 「タイムスタンプを指定して、それ以降のイベントをストリームで受信できる」
- 従来のPollingの機構を、頻度を下げつつ継続運⽤している - サービスメトリクスが⼀⾒変な内容になる - 「クエリが⻑時間実⾏され続けている」みたいな扱いになる - 監視の調整をすればよい話ではありつつ - 新しめの機能で、公式SDKでのコネクションの扱いが不安定だったりした - 急にSpannerインスタンス側からコネクションがDropされたりする - フォールバック機構を⼊れつつ、サポート依頼を投げたり - Subscriberをサービスプロセスに同居させるかは議論の余地がある - k8sを採⽤しているので、Outbox Sidecarとしてインスタンス分離した⽅がサービスレ ベルは上げられそう
まとめ - 分散トランザクションは難しいが、やる価値がある - マイクロサービスの⼤きな弱点の⼀つ - だからこそ、ここに決まったパターンを設定できると⼤きい - マイクロサービスのメリットを純粋に享受できる -
普段の普通の機能を作るときに意識することが減り、開発の速が上げられる - Goで作っていると、マイクロサービスの基盤に⼿を⼊れやすい - 今回みたいなアイデアを、軽量にプロセス内で試せる - ⾮同期プログラミングの強⼒さと、システムプログラミングの武器が揃っている
- もっと詳しく話を聞いてみたい - Gaudiyのこと気になるという方 ぜひカジュアル面談でお話しましょう!