DynamoDB Streams と lambda と SQS を連携させた際にストリームデータを効率よく処理させるために着目したこと

明けましておめでとうございます!auスマートパス開発部の新井です。

medibaで提供しているサービスではDynamoDBを利用しているサービスがあります。

Q: Amazon DynamoDB とは何ですか?

Amazon DynamoDB は、完全マネージド型の NoSQL データベースサービスであり、高速で予測可能なパフォーマンスとシームレスな拡張性が特長です。

https://aws.amazon.com/jp/dynamodb/faqs/

DynamoDBは、スループット容量を変更することができ必要なときに必要なだけリソースを利用することが可能です。

DynamoDB での制限について

ただ、スループット変更にあたっては制限があり増やす場合には日に何回でも可能ですが、減らす場合には日に4回という制限があります。

また、増やしたスループットが適用されるまでにはデータ量やデータ構造によって数分から数時間かかるという注意事項もあります。

Q: テーブルのプロビジョニングされたスループットレベルを変更するにはどのくらい時間がかかりますか?

通常、スループットを減らす場合は数秒から数分、増やす場合は数分から数時間かかります。 追加スループットが必要になった時点でスループットを増加したり増加のスケジュールを立てたりすることはお勧めできません。スループット容量のプロビジョニングは、必要なときに確実に容量を確保できるようかなり前から行っておくことをお勧めします。

https://aws.amazon.com/jp/dynamodb/faqs/

DynamoDB での制限一覧 https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/Limits.html

ユースケースに応じたデータストアの使い分け

DynamoDBを利用する際には、ユースケースに応じて必要となるスループットが異なるケースがあるため他のデータストアと併用する案の検討が大事かと思います。

  • フロントエンド

    • 訴求などによるスパイクアクセスにより特定の時間帯のみ高スループットが必要である
  • バックエンド

    • 日に一度だけ特定の時間帯に大量データを処理させるために高スループットが必要である

    • 運用者が任意のタイミングで格納されたデータを集計/出力するために高スループットが必要である

などなど

上記ケースの場合は、必要なときに都度スループットを変更することにより要求を満たすことは難しい状況となります。

また、バックエンドでのユースケースが実行されるタイミングでフロントエンドで利用しているテーブルのスループットを消費してしまうケースやバックエンドで利用するデータは、RDBMSで管理していたほうがデータを操作しやすいといった状況にもなります。

いつでも高スループット状態を確保できる状況であれば問題ありませんが、高スループット状態を確保しておくことにより費用面で課題が残ります。

そんなときには、DynamoDB Streams を利用することで別のデータストアへデータ同期することによりユースケース別に最適なデータストアの利用が可能となります。

データの流れイメージ

DynamoDB と RDS の併用をした際にストリームデータを効率よく処理させるために着目したこと

今回紹介させて頂く事例は、DynamoDB から RDS へデータを同期する際に、DynamoDB Strems と lambda間で効率よく SQS へメッセージを格納する処理にてパフォーマンスをあげるために工夫/検証した内容を紹介します。

Amazon Simple Queue Service(SQS)は、高速で、信頼性が高く、スケーラビリティに優れ、十分に管理されたメッセージキューサービスです。SQS を利用すると、簡単かつコスト効率良く、クラウドアプリケーションのコンポーネントを切り離すことができます。

※ 具体的な実装方法ではなく、パフォーマンス向上する上で着目したポイントの紹介となります。
※ lambdaからRDSへ直接連携させるためにはセキュリティグループの開放などが必要となりセキュアではなくなるためSQSを経由しています。
※ SQSからRDSへ効率よくデータを格納させる方法については触れていません。

着目ポイント1:DynamoDB Streams の Batch sizeについて

DynamoDB Stermsを有効にする際には、「Batch size」という項目を指定可能です。 Batch size を 変更することによりパフォーマンスにどのような影響があるのでしょうか。

※ Batch sizeで指定した値によって、ストリームデータが一度に処理される件数を指定することが可能となります。

着目ポイント2:lambda function から SQS へのメッセージを一度に送信する量について

SendMessage と SendMessageBatchを使うことによりパフォーマンスにどのような影響があるのでしょうか。

※ SendMessageは、一度に1件のメッセージを処理可能です。
※ SendMessageBatchは、一度に10件までのメッセージを処理可能です。

着目ポイント3:lambda function の割当てメモリ量について

lambda function の割当てメモリ量によりパフォーマンスにどのような影響があるのでしょうか。

※ lambda function のメモリ割当て量を大きくすることで性能は向上するのですが、パフォーマンス検証をしている際に考慮すべきポイントがあったため着目ポイントとして取り上げています。

着目ポイントに焦点を当てたパフォーマンス結果について

以下の結果となりました。

DynamoDBへの書込は100TPS(トランザクション毎秒)にて書込処理を実施し、SQSへのメッセージ処理においても100TPSに近しい値がでることを目的として検証した結果となります。

※ 利用したDynamoDBのテーブル構造、同期させる対象データ、lambda function等により異なる結果となるため、着目ポイントにおけるパフォーマンスがどのような相関関係となったかとして参照ください。

batch sizemessage type割当てメモリ量SQSへの処理性能(TPS)
1SendMessage128MB約6TPS
10SendMessageBatch128MB約45TPS
20SendMessageBatch128MB約50TPS
100SendMessageBatch128MB約65TPS
10SendMessageBatch256MB約77TPS

考えうる全ての組み合わせを試した結果ではありませんが着目ポイントを組み合わせることでパフォーマンスが向上することを確認できました。

まとめ

着目ポイント1:DynamoDB Streams の Batch sizeについて

Batch size を上げることにより、一度に処理される件数が増えるためパフォーマンスが向上する。

上記結果には含まれていないのですが、極端にBatch sizeをあげることにより一度に取り扱うストリームデータの量が大きくなりすぎ着目ポイント3の割当てメモリ量を超えてしまい、ストリームデータが取り残されるという事象が発生しました。

※ メモリ割当て量を増やすことで処理が実施されることは確認しました。

また、同様に極端にBatch sizeをあげることによりlambda functionの一度に取り扱うストリームデータ量が多くなりlambda functionのTimeout制限(デフォルト3秒)に引っかかりストリームデータが取り残されるという事象が発生しました。

※ Timeout値を伸ばすことにより処理が実施される形となります。

ただし、lambda functionのTimeout制限は最大60秒となるため最大60秒以内に処理が完了するBatch sizeを指定する必要があります。

着目ポイント2:lambda function から SQS へのメッセージを一度に送信する量について

SendMessageBatch にすることで、SQSへのメッセージ送信処理においてまとめてメッセージを送信することが可能となるためパフォーマンスが向上する。

注意点としては、batch sizeが 1の場合には、SendMessageBatchを利用したとしても一度に処理されるストリームデータは、1のためパフォーマンス効果はありません。 最低2以上に設定した場合のみ、SendMessageBatchを利用することでの性能向上が期待できます。

着目ポイント3:lambda function の割当てメモリ量について

割当てメモリ量を増やすことで、lambda自体の処理性能があがるため性能が向上する。

上記3つのポイントを処理をさせたい性能に合わせチューニングをすることでリアルタイムに近しい形でSQSへメッセージを格納することが可能かと思います。

最後に

今回紹介したパフォーマンスのチューニングポイントでは、SQSからRDSへもリアルタイムに近しい値でデータを同期させることは考慮できていません。

SQSからRDSへもリアルタイムに近しいデータを同期させるためには、SQSからのデータ取得間隔/Woker数、RDSへの書込性能などを考慮した上でチューニングを実施する必要がありますが、最終的にはDynamoDBにて確保する高スループット以上の書込性能をRDSで実現することは難しいと思われるためDynamoDBは、ユースケースに応じた利用することが大事だと思います。

DynamoDB Stremsについては、詳細な情報が公開されていない部分も多く、手探りで検証した結果となりますので 少しでも性能改善に役にたてれば幸いです。