helloworlds

not a noun, it's a verb

【AWS】DynamoDB Streams & Lambdaの関係

SQSのメッセージについて更新しました(記事下部に記載)

LambdaとSQS,DynamoDBの連携について、メモがてら実際試したことを書きます。

よく構成としてEC2を起動させて、SQSをポーリングしたりするかと思いますが、 近年だとLambdaのCLoudwatch Eventsなどを使用して定期的にSQSをポーリングさせたりしています。

日頃の運用として、DBに更新処理がかかったときに、その更新をトリガーとし なにか他の処理が行われるなんてことも大いにありそうですね。

AWSのサービスでいうと、DynamoDB Streamsだったり、 Kinesis Data Streamsだったりなんかを使用している方は多そうです。

そこで今回注目するのは、Lambdaの同時実行数やメモリサイズなどです。

DynamoDB Streams

DynamoDB Streamsを有効化していると、(DynamoDB Streamsは非同期で動作するので実際のテーブルのパフォーマンスに影響することはないそうです) アプリケーションはDynamoDB Streamsエンドポイントに接続してAPIをリクエストする必要があります。

このDynamoDB Streamsは、ストリームレコードというもので構成されていて、 ストリームレコード1件は、テーブル内の1件のデータ変更です。 このストリームレコードには、シーケンス番号が発行されます。

このストリームレコードの集合をシャードといいます。 シャードは、24時間後に自動的に削除されるそうですが、確かめてはいません。

細かい部分ではありますが、1つ気をつけることがあります。

DynamoDB Streamsを有効→無効→有効

シャードがなくなるかと思って、1度無効化にして再度有効化すると、 無効化する前のシャードは再び動き始めます。

また、このシャードは、Lambdaの同時実行数に関係してきます。

Lambdaの同時実行数 = DynamoDB Streamsシャード数

つまり、どんなにレコードに多く変更がかかってもシャード数自体が増えなければ、Lambdaの数は同等で、多く早くデータをさばきたくてもさばけないなんて状況になり得ます。

(※ シャード数は、DynamoDBテーブルのパーティション数と連動する!)

Lambdaのあれやこれ

上記で説明したLambdaとDynamoDB Streamsの連動でうまくいかいない時、 単純にパーティション数を増加させようとしますが、それはよく考慮する必要があります。

まず、最初にLmabdaをできるだけ高速化させることが重要です。

Lambdaの設定を見直してみましょう。

メモリ

デフォルトでは、128 MBで設定されていると思います。 この値は、MAX 3008 MB(およそ3 GB)まで上げることが可能です。

メモリを増加させることで、CPU性能の増加が期待できます。

しかし、単純にメモリサイズを増加させるだけはいかないことがわかりました。

Batchsize

テーブルに対してBatchsizeが設定されています。(AWSのコンソール、各Lambdaのページから確認可能) デフォルト値は、100だと思います。 これも増加させることで、Lambdaの1 Invocationあたりの処理レコード数を増加させることができます。

ここで、よく判断しないといけないことが...

メモリサイズの増加でDuration(呼び出しの結果として関数コードが実行を開始してから関数の実行が停止されるまでの実時間)の 低下をまず確認してからでないと、Batchsizeを上げても効果が得られないこと。

そして、Lambdaのペイロードサイズである 6 MB以内のレコードであること。 レコードのサイズが非常に高いとBatchsizeを上げても意味がない。

  • Lambdaの詳細をcliで確認
aws lambda list-event-source-mappings --function-name your-function \
    --profile profile-name --region your-region
  • Batchsizeを変更(uuidを上記コマンドで確認)
aws lambda update-event-source-mapping \
    --uuid "value" \
    --batch-size number \
    --profile profile-name --region your-region

そして最後のSQSです。

LambdaとSQSがポーリングしていて、尚且つレコード数が多い場合です。

DynamoDB Streamsから流れてきたレコードがLambdaへ渡り、SQSへいきますが、 SQSのドキュメントを確認すると、スタンダードキューの場合、キューあたり12万件までとなっています。

もし、大量(大量というのは100万件以上くらいかな?)のレコードに一気に変更がかかった場合、

-------更新範囲

パンクしないか?と、心配になってしまいます。

コチラ↑ SQSの公式ドキュメントと検証で理解しました。 SQSのメッセージは、ドキュメント上2つの種類がある(2つあると認識するかはその人次第です。ドキュメントを読む中で用語と仕組みをある程度完璧に認識して切り分けができている人は当たり前なことだと思います。私は読んでいて当初、インフライトメッセージというものが理解できずにいたためです)ということです。

ドキュメント上、メッセージとインフライトメッセージは別と考えましょう。

公式では、 「キューには最大 120,000 のインフライトメッセージが存在できます」と記載があります。

このインフライトメッセージというのは、 「キューから受信されたメッセージで可視性タイムアウト内にあって、まだキューから削除されていないメッセージ」 このことを指します。

よって、キューが持てるメッセージ数には制限がないという認識で問題ないです。

-------更新範囲

利用可能なメッセージがたーっくさん溜まっても、それと連動するサービスの処理速度をあげれば、問題なさそうでした。

40万件くらいたまりましたが、エラーなどは表示されず。

メッセージキューに含めるメッセージ数に制限はないと公式ドキュメントに書いてありますね。 ただ、転送中メッセージ数についてスタンダードキューで12万件という制限があるとも公式に記載があります。

これらを考慮して、3サービスをうまく活用していけたらと思います。 そして、一番重要なのは、よくドキュメントを読むことです。 勿論テストしたり、手を動かすことも大切ですが、ドキュメントに書いてある用語なり サービスの仕組みを理解することで、より具体的に調査やテストが可能だと思います。