MEGAZONE

MEGAZONEブログ

Serverless data streaming: Amazon Kinesis Data Streams and AWS Lambda
Data & Analytics re:Invent 2023

Serverless data streaming: Amazon Kinesis Data Streams and AWS Lambda

Pulisher : Cloud Technology Center キム・ビョンジュ
Description : Amazon Kinesis Data StreamsとLambdaを使った経験と失敗事例から得た内容についての紹介セッション

Kinesis Data Streamsはリアルタイムデータ処理アーキテクチャでMSK, Kafkaと同じようによく使われるサービスです。一般的にKinesis Data StreamsはKDHとよく使われます(直接開発の難しさなど)。 また、リアルタイムデータ処理であるため、サーバーレスを維持することも非常に難しい問題です。 このような問題点をどのような方法で解決し、どのように考えるか一緒に考え、より良いアーキテクチャを提供することが今回のセッションの目標です。

このセッションでは、AWS Data Heroとして活動しているAnahit Pogosovaが経験したAmazon Kinesis Data StreamsとLambdaを使った経験と失敗事例を一緒に公開し、そこから得た経験を紹介します。

最近、このようなアーキテクチャが人気を集めています。 理由を簡単に確認すると、次のようになります。
・準リアルタイムのデータ分析が可能で
・非同期アーキテクチャの一つであるstorage-firstを使います。
・シンプルだけど強力です。

まず、このアーキテクチャのメインであるKinesis Data Streamについて説明します。Fully managedでサイズ変更が容易なストリームデータサービスです。データはmilliseconds単位で入ってきて、最低24時間保管すれば最大365日保管することができます。

Kinesisはサーバーレスと紹介されています。しかし、本当にサーバーレスなのでしょうか?上記のようなデータ取得パターンがあるとしたら、直接ReShardingとAuto Scalingが直接コントロールする必要があります。 では、なぜAWSはこれをサーバーレスと呼ぶのでしょうか?

なぜなら、オンデマンドがあるため、自動的にスケーリングとリシャードが行われるため、本当のサーバーレスのように感じられます。 しかし、私が期待していたのと違って動作しました。拡張は自動でできましたが、オーバープロビジョニングされすぎてコストが高くなりました。 このような内容は、導入する前に知っておくべきトレードオフです。

それでProvisionedで直接制御するのもいい方法ですし、On-demandモードを使うのもいい方法です。とりあえずはOn-demandモードで使って直接ストリームデータを処理してみたり、モニタリングでProvisionedモードに切り替えて使うこともできます。

私たちはLambdaをconsumerとして選択することで、本当に様々な利点があると考え、Lambdaを選択しました。 そして、AWSの様々なサービスの中でKinesisをサポートし、Kinesisに基づいて実装されているサービスも多くあります。 これは大きな利点です。 それでは、詳細を説明しましょう。

私たちはKinesisを使う中で本当に重要なエラーに出会いました。putRecordsというapiを使ってKinesisにrecordsを入れると、最大500レコードもしくは5MiBサイズでデータを入れることができました。

そこで私たちは、従来3つに分離されたレコードをそれぞれ入れる方式で作業していた場合、そのエラーに遭遇した後、レコードを結合して転送しました。 また、このように多くのレコードを分離して転送するということは、producerにレイテンシーを増加させることを意味します。

では、Kinesisにデータを書き込む際に失敗した場合、どのような問題が発生するのでしょうか?AWS SDKでは自動的に3回の再処理試行間隔(100ms)を基本的に適用して適用します。しかし、2分間再試行することになります。しかし、考えてみましょう。2分? 私たちはリアルタイムデータを処理しており、その程度を待つことができないので、私たちはTimeout時間を短くしました。

部分的な失敗と再試行については、大きく2つだけ指定すればよいです。一つ目はretriesにlimitを設定することと、再試行をする時、システムが準備されていない状況で急に再始動をしてはいけないので、追加的なbackoffが必要です。私はそのようなバックオフの問題をjitterで簡単に解決しました。

しかし、根本的になぜこのようなエラーが発生するのでしょうか?Kinesisは基本的にシャードごとに性能に限界が存在するからです。 1分間に2000件のログが発生すると仮定しても、1500件が一度に殺到した場合、Kinesisはデータを処理できずエラーを返します。

まとめると、KDSにデータを書き込むためには、3つの点に留意する必要があります。部分的な失敗に対する再試行が必要です。 retryとtimeoutに対する適切な設定が必要です。より詳細なmetricsを見れるようにする必要があります。次はLambdaを使って読むことについて説明します。

ESM(Event Source Mapping)を通じてラムダから簡単にKinesisデータを取得して処理することができます。基本的に1 Batch当たり1ラムダを割り当てて処理し、1つのシャード当たり1つのラムダが実行されます。しかし、最大シャード当たり10個のConcurrencyを持つことができ、それにもかかわらず、ラムダの同時性を警戒しなければなりません。いくらラムダの同時性を増やしても、結局は限界があり、エラーが発生します。

そしてまた、ラムダが一つのバッチを処理するのに失敗したら、データが消失するまでずっと…ずっと…ずっと…ずっと再試行します(成功するまで)。そして、一つのBatchで一つのレコードが失敗したら、ラムダ全体を再試行します。

それで一番重要なことは再処理回数を制限することです。 そして、最大処理するrecord ageを指定して範囲を決めることです。 さらに、Return partial success を使って処理に失敗したsequence Numberの値を返すことができます。これによってそのsequence Numberを再処理しなくて済みます。一番大事なこと 基本を使わないでください!

さらに、Filter recordsを使用してみてください。filterを使うとラムダの実行を減らすことができ、「poison pill」にやられる確率も減らすことができ、より少ないカスタムコードを使うことができます。

最後に、人生は一つのトレードオフのようなものです。 一つを選択すると、もう一つを失うことになり、それを心に留めておく必要があり、どのようなサービスを利用する際、どのように機能するかについて考えて使用することが重要です。私たちはそのような部分を簡単に見逃してしまいます。 そして、失敗を受け入れましょう!

‘基本設定値を使わないでください’本当に重要な一言ではないかと思います。私たちはAWS内でサービスを扱っていると、Docsを何も考えずにそのまま使うことがとても多いです。 一般的にそのような方法はうまく動作する場合もあるので、さらにそうです。 しかし、もう少しハードなサービスを使うようになると、すぐに問題に直面することになります。Kinesisのデータ処理で出会えるSDK上のエラーも非常に興味深いセッションだったと思います。

ブログ一覧

この記事の読者はこんな記事も読んでいます