Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Spanner Change StreamによるTransactional Outboxでの ...
Search
Satoshi Amemiya
October 14, 2025
95
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Spanner Change StreamによるTransactional Outboxでの 分散トランザクションの高速化
Satoshi Amemiya
October 14, 2025
Featured
See All Featured
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3.8k
Making Projects Easy
brettharned
120
6.8k
The State of eCommerce SEO: How to Win in Today's Products SERPs - #SEOweek
aleyda
2
12k
SEO in 2025: How to Prepare for the Future of Search
ipullrank
3
3.9k
Accessibility Awareness
sabderemane
1
250
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
440
Designing for humans not robots
tammielis
254
26k
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
630
How Software Deployment tools have changed in the past 20 years
geshan
2
35k
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
1.1k
Music & Morning Musume
bryan
48
7.4k
Ten Tips & Tricks for a 🌱 transition
stuffmc
1
270
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のこと気になるという方 ぜひカジュアル面談でお話しましょう!