みなさん。こんばんは。サニービュー事業部の小寺です。今日はAWS Lambdaなどのサーバレスサービスを使う上で「冪等性(べき等性)」について、お伝えしたいと思います。

まず、べき等性ってお聞きになったことがありますか。

べき等性とは?

べき等性とは、「何回実行しても実行結果が同じ状態になる」ことを意味します。 サーバレスのプログラミングにおいて、べき等性とは、イベントの 繰り返しを識別し、データの重複、矛盾、損失を防ぐアプリケーションまたはコンポーネントの能力です。 AWS Lambdaの関数でべき等性を維持した設計にするためには、重複するイベントを正しく処理するように関数ロジックを設計する必要があります。

また、べき等性があれば、以下の課題を減らしていくことにも役立ちます。

  • 不要な API 呼び出し
  • コードの処理時間
  • データの不整合
  • スロットル
  • レイテンシー

例えば、Lambda関数でファイルをPUTする処理を考えてみましょう。べき等性がある処理では、何回関数を実行してもファイルは1つで内容が同じ状態を維持します。

一方、べき等性がない処理では関数を何回か実行してしまい、重複するイベントが発生すると、テーブルのデータ件数が変わってしまいます。

なぜべき等性が必要なの?

ここまで、べき等性についてお伝えしてきましたが、そもそもなぜべき等性が必要なのでしょうか。重要なのはこの2点です。

  1. マイクロサービス / サーバーレスでは、一つの処理単位が小さく独立している
  2. サーバーレスでは、リトライが自動で実行されることがある

一般的にはサーバレスではないアプリケーション開発では、一つの処理がサーバレスよりは大きく、独立しています。そのため処理が正常終了となる場合は良いのですが、正常終了しなかった場合、 つまり問題や障害が起きた場合や関数実行時の対応が変わってきます。キャンセル処理をどのように考慮するか?といったことがサーバレスとそうではないアプリケーション開発で異なってくるというイメージが正しいです。また、 おもに処理を行う際になにかのデータストアに書き込みをするような処理があるか?ないか?で変わってきます。

リトライについては、マイクロサービスに該当する処理関数 (AWS Lambda) のリトライ処理が自動で行われる設定が元々あります。例えば、Amazon S3 → AWS Lambda の連携処理などでの リトライの自動管理・実行 が例として挙げられます。リトライは、Lambda 関数のコード実装の不備や実行時メモリ不足などにより関数実行が正常に終了しないケースで行われます。

また、サーバレスの代表的なサービスLambdaでは、リトライ含め、まれに多重実行がされてしまうことがあります。

べき等性を考慮するには

何を考慮すれば、べき等性を考慮したことになるのでしょうか。

Lambda コードは、重複イベントを処理するときにエラーを生成せずに終了するようにしてください。
注: エラーを発生させると、Lambda や関数を呼び出す他のサービスが、試行を何度も繰り返す可能性があります。

必要に応じて Lambda 関数のタイムアウト設定を変更し、ランタイム全体が正しく処理されるようにします。
注: 別のサービスを使ってデータを保持し、重複するイベントを制御するには、HTTPS エンドポイントへの API 呼び出しが必要になる場合があります。HTTPS エンドポイントへの API 呼び出しでは、デフォルトの 3 秒よりも多くのランタイムが必要になる場合があります。

できる限り関数をテストして最適化し、実際のシナリオと要求率をシミュレートします。
注: 冪等関数ロジックのテストと最適化は、タイムアウト、過度の遅延、ボトルネックなどの潜在的な副作用を防ぐために重要です。

スケーリングが容易でスループットが高い DynamoDB などのサービスを使用して、セッションデータを保存します。

注:Amazon Elastic Compute Cloud (Amazon EC2) への API 呼び出しを行う場合、このサービスで clientToken パラメータが提供されます。clientToken を使用すると、API リクエストが再試行された場合にのみ、変更 API リクエストが 1 回実行されるようにできます。

https://aws.amazon.com/jp/premiumsupport/knowledge-center/lambda-function-idempotent/

無限にループしてしまったり、実行結果を一意に保つためには上記をまず理解することが大切です。そして、あくまで一例ではありますが、LambdaとSQSを組み合わせてS3にデータ書き込みを行ったりする際に、自分自身を関数として呼び出さないようにしましょう。また、テストも行った上で、モニタリングしていくことも重要です。

いかがでしたでしょうか。今日はべき等性についてのお話でした。Lambdaは使ったこともないという方もいらっしゃる一方で、ほとんどサーバレスという方もいて、二分されるのではないかな、と思います。