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

サーバーレスから Durable Execution へ

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for acomagu acomagu
August 06, 2026

サーバーレスから Durable Execution へ

Avatar for acomagu

acomagu

August 06, 2026

More Decks by acomagu

Other Decks in Programming

Transcript

  1. “Serverless Computing: One Step Forward, Two Steps Back,” CIDR 2019

    - Scalable Data Processing: クラウドには巨大なストレージと計算能力があるので、 大規模データを効率的に処理 できる - Distributed Computing: クラウドには数百万規模のコアがあるので、多数の計算主 体を協調させる分散プログラム を書ける
  2. “Serverless Computing: One Step Forward, Two Steps Back,” CIDR 2019

    - Scalable Data Processing: クラウドには巨大なストレージと計算能力があるので、 大規模データを効率的に処理 できる - Distributed Computing: クラウドには数百万規模のコアがあるので、多数の計算主 体を協調させる分散プログラム を書ける
  3. “Serverless Computing: One Step Forward, Two Steps Back,” CIDR 2019

    - Scalable Data Processing: クラウドには巨大なストレージと計算能力があるので、 大規模データを効率的に処理 できる - Distributed Computing: クラウドには数百万規模のコアがあるので、多数の計算主 体を協調させる分散プログラム を書ける サーバーレスになった途端 できなくなったじゃねぇか オイ!!!!!
  4. 筆者らはどのような実験を行ったのか 対象: 2018 年当時の AWS サービス(主に EC2 vs Lambda +

    SQS + DynamoDB) 1. 機械学習モデルのトレーニング Lambda版は約21倍遅く、約7.3倍高価 2. バッチ処理 Lambda版は127倍遅かった 3. Lambda インスタンス間でのリーダー選出&合意形成 1回のリーダー選出に16.7秒かかり、1,000ノードを維持する場合のDynamoDB利用 料も非常に高い
  5. なぜこんなに差が出たのか? 理由① データを読み込む 理由② DynamoDB / S3 処理する Lambda Lambda

    Instance A Lambda Instance B 永続化する DynamoDB / S3 データの転送が遅い Lambda インスタンス間で 低遅延で通信する方法がない
  6. 1973年: Actor の誕生 Actor は「将来、数百・数千のマイクロプロセッサから構成され、個々にローカルメモリ を持ち、高性能通信ネットワークで通信を行う並列コンピュータ が登場するだろう」とい う予測に基づいて開発されたアーキテクチャ (… FaaS

    かな?) Actor は: - 1 Actor : 1 プロセッサ(メモリも共有しない) 任意の数の「子 Actor」をスポーンできる 他の Actor や子 Actor に、(Actor の ID を使って)メッセージを送信できる 受け取ったメッセージに対して振る舞いを行う という特徴を持つ
  7. 2014 年: Virtual Actor の誕生 Microsoft が出した Orleans というプロダクトのホワイトペーパーで、「Virtual Actor」とい

    う概念が初出する。 Virtual Actor とは「任意の ID で区別される、独自のストレージを持つもの」 。さらに、 親子関係や起動/配置/終了の概念がなくなった (物理的なプロセスから、論理的な存 在へ) より具体的には: - Actor は子 Actor をスポーンする代わりに「任意の ID の Actor」にメッセージを送 れる。その ID の Actor がまだ存在しなければ自動で新規作成される 各 Actor は常にメモリ上に読み込まれているわけではなく、しばらくメッセージを受 け取らなければ状態を保存してスリープする
  8. 2014 年: Virtual Actor の誕生 「独自のストレージを持つ」? なぜ? 「プログラムにデータを送るのではなく、データのあるところにプログラムを送る」ため Function-shipping ではなく、Command-shipping

    として実現している 「ストレージを持った Actor」自体は Orleans 以前にも「Persisted Actor」など似たような 構成はあった。しかし Orleans はこの特徴を「自動スリープ」「自動ライフサイクル」の特 徴と組み合わせることで、FaaS のような「使った分だけリソースが消費される」特徴と 「データのあるところに関数がある(データ局所性)」を両立させる ことに成功した(具体 的には、コールドスタート時に関連するデータを全て持ってくる)
  9. 2014 年: Virtual Actor の誕生 「Virtual Actor 最高じゃん! …え、Two Steps

    Back 論文(2019)では言及なし?」 Orleans は実は Azure のサービスではなく、.NET のライブラリとして開発された。この時 点では全くサーバーレスの文脈では語られていなかった。 しかし6年後...
  10. 2020年: Cloudflare Durable Objects 発表 - DO は、V8 Isolation(Cloudflare Workers

    基盤)上で動く JavaScript クラス。1つの ID について常に高々 1 クラスインスタンスが保証されている。 - DO は「任意の ID の DO」にメッセージを送れる。その ID の DO がまだ存在しなけ れば自動で新規作成される - 他の DO とは共有しない、独自の SQLite(2020年発表時は KV Store)を持つ - - これは DO と同じマシン・SSDで読み書きされることが保証される(ネットワークを介しない) 数十秒アイドル状態で自動でメモリから排除される。 非常に Orleans の Virtual Actor と似た特徴を備えたサーバーレス商品
  11. 2023年: Restate Virtual Objects Apache Flink の開発者が Apache Flink の経験を元にした、Restate

    が発表 - 任意のクラウドベンダのコード実行環境(Lambda や Cloud Run など)をVirtual Object 化できる コールドスタート時に、その Virtual Object の状態全体を送信するので、ホット状態 であればメモリ上の読み書きで済む
  12. なぜこんなに差が出たのか? 理由① データを読み込む 理由② DynamoDB / S3 処理する Lambda Lambda

    Instance A Lambda Instance B 永続化する DynamoDB / S3 データの転送が遅い Lambda インスタンス間で 低遅延で通信する方法がない
  13. なぜこんなに差が出たのか? 理由① データを読み込む 理由② DynamoDB / S3 処理する Lambda Virtual

    Actor 系列のサーバーレスが Function-shipping で解決 Lambda Instance A Lambda Instance B 永続化する DynamoDB / S3 データの転送が遅い Lambda インスタンス間で 低遅延で通信する方法がない
  14. なぜこんなに差が出たのか? 理由① データを読み込む 理由② DynamoDB / S3 処理する Lambda Virtual

    Actor 系列のサーバーレスが Function-shipping で解決 Lambda Lambda Virtual Actor 系列のサーバーレスが Instance A Instance B Actor の ID で解決 永続化する DynamoDB / S3 データの転送が遅い Lambda インスタンス間で 低遅延で通信する方法がない
  15. しかしデメリットも... Cloudflare Durable Objects は > 一つのDOは一台のマシン上の単一スレッドで処理されるため、同じIDへ極端にアクセ スが集中すると、そのDOがボトルネックになります。DO はscale upではなくscale

    outを 前提とし、単一オブジェクトの処理能力を超える場合にはシャーディングや集約構造が 必要 という説明をしている 「1つの Durable Object 自体のスケールには限界がある」 「リクエストはデータ間で分散するはず」という予測から、無限のスケーリングを諦めてい る
  16. Orleans では? 「口座間で資金を移動する」 という Python コード 「複数の口座 Actor を同時に ロックする」ことで実現している

    with (yield context.lock([source, destination])): balance = yield context.call_entity(source, "get") if balance < amount: return False yield context.task_all([ context.call_entity(source, "withdraw", amount), context.call_entity(destination, "deposit", amount) ]) return True
  17. Orleans では? 「口座間で資金を移動する」 という Python コード 「複数の口座 Actor を同時に ロックする」ことで実現している

    with (yield context.lock([source, destination])): balance = yield context.call_entity(source, "get") if balance < amount: return False yield context.task_all([ context.call_entity(source, "withdraw", amount), context.call_entity(destination, "deposit", amount) ]) でも Stripe はロックできない...! return True
  18. Saga パターンを(伝統的な)FaaS で実装しようとすると? Func1 -> SQS -> Func2 -> SQS

    -> Func3 … 更に - 定期的なリトライ ローカルトランザクションでのコミット(永続化) ロールバック 上記を自分で実装する必要がある
  19. 2017年: Azure Durable Functions AWS SWF に関わった Samar Abbas が「(JSONではなく)C#

    の async/await でワークフ ローを書ける」ものを開発
  20. 例えばさっきの「送金」の例を Saga でやるなら: try { const transferId = ctx.uuid(); const

    reserved = await ctx.run(() => sourceAccount.withdraw({ amount })); compensations.push(() => ctx.objectClient(account, source).cancel(transferId)); await ctx.run(() => destinationAccount.deposit({ transferId, amount })); compensations.push(() => destinationAccount.cancel(transferId)); } catch (e) { // 一時障害は Restateに再試行させ、 // 恒久的な失敗の場合だけ補償する。 if (e instanceof restate.TerminalError) { for (const compensate of compensations.reverse()) { await ctx.run(() => compensate()); } } }
  21. どういう仕組み? ctx.run(() -> { … }) に渡した関数は、下記の特徴を持つ: - 失敗時にリトライされる 成功時は、結果が保存され、2度実行されることはない

    また、ctx.sleep(1 days)で 1 日待ったりすることもできる。もちろんその間プロセスが持続 することはない。それまでのコードの結果が全て保存されているので、そこまで「リプレ イ」することで、1日後にまた副作用を重複して起こさずにコードをそこまで進めることが できる。
  22. “Durable” とは何なのか? 従来型のサーバーレスは「オートスケール」「Pay as-you-go」という特性のために、「短 命のコンピュート」の手法を推し進めた。 しかし、「短命のコンピュート」で「長寿命なアプリケーション」を実現するために、無理が 必要な場面もあった: - 計算資源はスケール可能だが、データのスケールは難しいため、結果的にデータ とプログラムがネットワーク越しに離れたものになってしまった

    オートスケーリングのために1インスタンスは「無名」なものになり、インスタンス同士 の連携が難しくなった 「短命なコンピュート」を組み合わせると並列処理と分散コンピューティングと付き合 わなければならないが、分散コンピューティングの本質的な難しさに対処するため の簡単な処方箋は長らく存在しなかった
  23. “Durable” とは何なのか? Durable とは「長寿命な」という意味で捉えている。つまり、サーバーレスという「短命なコ ンピュート」上で、「長寿命なアプリケーション」を構築するための新しい部品が、Durable Functions や Durable Objects。 Actor

    系列の Durable Objects 等は「リクエストはデータ間で分散するはず」という予測 から、無限のスケーリングを一部諦めて、「Actor(JS クラス+データなど)」を長寿命化し た。 Workflow Engine 系列の Lambda Durable Functions 等は、「リプレイ」という仕組みに よって、短時間のコンピュートであたかも長時間1つの関数が実行可能なように見える仕 組みを構築した