OSDIで行われた以下の発表の資料を読んでいて、「Exactly-once semanticsってなんだっけ?」と疑問に思い、調べたことのメモ。
Fault-tolerant and transactional stateful serverless workflows | USENIX"Fault-tolerant and transactional stateful serverless workflows" https://t.co/i4L2jLYIlQ from Zhang et al was a good read. Stateful serverless is a great research area, and this is a smart approach to some aspects of the problem. A couple comments:
— Marc Brooker (@MarcJBrooker) 2020年11月10日
ApacheKafkaとexactly-once semantics
- transactional message processingにおいては、「PublisherからSibscriverへmessageの伝送が重複も欠損もなしに届くことは保証可能か」という問題領域が存在する
- 上記の「messageの伝送が重複/欠損なしに実行される」性質を exactly-once semantics と呼ぶ
- 要するに、Publisherが1Messageを送信したら、Subscriverに重複も欠損もなしに1通だけが届いてほしい
- Apache Kafkaにおいて、Confuent社が2017年にexactly-once semanticsを保証する機能を発表し話題になった
3種類のSemantics
Exactly-once semantics が成立するためには、以下の2つのsemanticsの両方が保証される必要がある。
- (1)メッセージが最低1回は送信されること(at-least once semantics)
- (2)メッセージが最大でも1回しか送信されないこと(at-most once semantics)
いずれか片方のみのが満たされる場合は以下の状態になる。
- at-least onceのみの場合、メッセージの重複が許容される
- at-most onceの場合、メッセージの欠損が許容される
保証の方法だが、at-least once を保証しようとすると、「処理失敗時の再送(再実行)は可能か?」みたいなことを考えていくことになる。また、at-most once は、「この処理は実行されました」的なフラグをDB等の外部サービスに保存することで実現可能である。
AWS LambdaとExactly once semantics
2020年11月現在、AWS Lambdaでは、At-least once semanticsのみが保証されている。つまり、Functionが複数回実行されてしまうことが起こりえるため、プログラムを 冪等(idempotent) に設計することが求められる。
冪等性(idempotent)の定義
関数が1回実行された時もN(>0)回実行された時も結果が変わらない
こと- 「ある変数(int)の値を10にする」 → 冪等な処理
- 「10を加算する」→ 冪等な処理ではない ※但し、後述のAWS推奨の方法にように制御構文により1回しか更新が実行されないことが保証できるなら冪等
推奨される冪等性(idempotent)の実現方法
AWSのドキュメントでは以下のように、処理成功時にeventIdを外部DBに保存し、「処理完了フラグ」のように使う方法が推奨されている
- 入力イベントの固有属性の値を抽出します。入力イベントの固有属性の値を抽出します。
- 属性値がコントロールデータベース (Amazon DynamoDB テーブルなど) に存在するかどうかを確認します。 注: アーキテクチャに AWS サービスを追加すると、追加費用が発生する場合があります。詳細については、「Amazon DynamoDB 料金」および「 AWS 料金」をご参照ください。
- 一意の値が存在する場合 (重複イベントを示す)、実行を正常に終了します (つまりエラーを発生することがない)。一意の値が存在しない場合は、通常の実行を継続します。
- 関数の動作が正常に終了したら、コントロールデータベースにレコードが含まれます。
- 実行を終了します。
FaaSにおいて、基盤側にてExactly-onceを保証することは可能か?
- 冒頭の論文でやり方が提案されている。興味のある方はそちらを参照。