re:Invent 2025: DynamoDBのパーティショニングとレイテンシー問題の実践的解決事例
はじめに
海外の様々な講演を日本語記事に書き起こすことで、隠れた良質な情報をもっと身近なものに。そんなコンセプトで進める本企画で今回取り上げるプレゼンテーションはこちら!
re:Invent 2025 の書き起こし記事については、こちらの Spreadsheet に情報をまとめています。合わせてご確認ください
📖 re:Invent 2025: AWS re:Invent 2025 - Dive deep into Amazon DynamoDB (DAT435)
この動画では、DynamoDBのSenior Principal EngineerであるAmrithが、実際の顧客事例を通じてDynamoDBのアーキテクチャを解説しています。DynamoDBは1秒あたり数億リクエストを処理し、ほとんどが1桁ミリ秒で完了する規模で動作します。第一の事例では、匿名性を重視した投票アプリケーションが800 TPSでwrite throttlingに直面した問題を取り上げます。原因はハッシュベースのパーティショニングにおける決定論的ハッシュの特性で、一つのテーブルをスキャンして別のテーブルに同じキーで書き込むと、トラフィックが特定のパーティションに集中してしまいます。解決策としてIDの前に2文字を付加することでハッシュ値を分散させ、90,000 TPSでのベンチマークに成功しました。第二の事例では、高トラフィック時に低レイテンシー、低トラフィック時に高レイテンシーという直感に反する現象を分析します。これはリクエストルーターのキャッシュ効果が得られていないことが原因で、低トラフィックを少数のホストに集約することで解決しました。
※ こちらは既存の講演の内容を最大限維持しつつ自動生成した記事になります。誤字脱字や誤った内容が記載される可能性がありますのでご留意下さい。
本編
DynamoDBの深い掘り下げ:予測可能な低レイテンシーとスケーラビリティの実現
DynamoDB についての深い掘り下げのお話です。まず最初に申し上げたいのは、皆さんにはいろいろな選択肢があるということです。今この瞬間にも、たくさんのセッションが開催されています。このセッションに来ていただき、ありがとうございます。オンラインで視聴されている方も、ありがとうございます。
毎年このトークをするときに、なぜこういったトークをするのかということを考えます。シンプルな答えは、皆さんのためということです。私が今の仕事で最も好きなことは、皆さんと一緒に働いて、DynamoDB を使って、そして過去には他のデータベースを使って、皆さんが作っているものを見ることです。
今年は、ちょっと違うアプローチをしてみようと思いました。過去のプレゼンテーションでは、ブロック図やアーキテクチャなどを中心にしていました。今年は、それを変えてみることにしました。同じことをやるんですが、顧客の視点からやってみようと思います。実際の顧客との 2 つの実例を取り上げて、彼らが報告した問題について話し、そしてそのレンズを通してアーキテクチャについて話します。
簡単に自己紹介をさせてください。私の名前は Amrith です。Senior Principal Engineer をしています。DynamoDB チームに約 6 年間いますし、この業界には約 35 年間います。これまでの役職で最も好きなことは、顧客と一緒に働くことです。ですから、このトークの後、もし質問があれば、ぜひお気軽にお声がけください。さっそく始めましょう。
では、DynamoDB とは何か。それはドキュメント型およびキーバリュー型のストアです。そして、私たちの目標は、どのようなスケールでも予測可能で低いレイテンシーを皆さんに提供することです。この 2 つのことを考えてください。予測可能で低いレイテンシー、そしてどのようなスケールでも対応できるということです。通常、DynamoDB は基盤となるサービスで使われているのを見かけます。
foundational services とは何かというと、ログインのようなもの、システムに接続する能力、inventory management、つまり amazon.com のほとんどのようなものです。AWS は DynamoDB で動いています。ほとんどのサービスの control plane は DynamoDB で動いています。これらは latency と availability が最も重要なアプリケーションです。予測可能で低い latency、そして非常に高い availability について話しています。5 nines を大きく上回るレベルを達成していて、ほとんどのリクエストは 1 桁のミリ秒で完了します。
重要なのは、お客様がこれらの機能を提供するために私たちが行っているすべてのことについて心配する必要がないということです。データを取得して、データを入れる、それだけです。あらゆるスケールで完全に管理されています。1 秒あたり 10 リクエストであろうと、1 秒あたり 10,000 リクエストであろうと、あるいは 1 秒あたり 50 万リクエストを継続的に処理している数百のお客様がいますが、同じ latency が得られます。同じ予測可能な latency を提供することを目指しています。
DynamoDBが処理する圧倒的なスケール:1分で満たされるプール
スケールについて何度も話してきました。それが何を意味するのか、感覚をつかんでもらいたいと思います。これはオリンピックサイズのスイミングプールです。どうやらこれはバルセロナにあるようです。50 メートル × 25 メートル × 2 メートルです。世界のほとんどの地域の人々は 2,500 立方メートルを理解していますが、米国ではそのようにはしません。私たちはフットボールフィールドやジャンボジェットの大きさで物の大きさを伝える必要があります。ここにいる私たち全員にとって、これは 17,000 個のバスタブ、おそらくメートル法のバスタブです。
プールからすべての水を取り出して、17,000 個のバスタブを米粒で満たすと仮定しましょう。誰もがどのくらいの大きさかを知っています。私はそれがどのくらいかは言いません。DynamoDB が処理するすべてのリクエストに対して、今は空になっているスイミングプールに米粒を 1 粒置きます。このスイミングプールを満たすのに何日かかると思いますか?
1 日未満です。わかりました、勇敢な方がいますね。このスライドを話し終わるまでの時間より短い時間で、そのスイミングプールを満たしてしまいます。これが私たちが動作しているスケールの概念です。amazon.com にアクセスするたびに、カートに何かを入れたり、検索したり、DynamoDB を使用している多くのアプリケーションのいずれかを使用したりするたびに、米粒 1 粒、61 秒で、満杯のスイミングプールが完成します。ですから、スケールについて話すときはこれを念頭に置いてください。
アプリケーションがスケールできるかどうか、あるいは私たちがそれをサーブできるかどうかについて懸念がある場合、答えはイエスです。
1分間に17,000個のバスタブを覚えておいてください。 では、これら2つのケーススタディの最初のものについて話しましょう。人生は短すぎて 楽しむことなく過ごすべきではないというのが私の固い信念です。ですから、皆さんも楽しみながら、同時に何か学べることを願っています。これは実際の顧客インシデントです。 顧客の名前は明かしませんが、これは文字通り起こったことです。この問題が最初に発生したとき、私たちはあなたがこれを見たときおそらく困惑するのと同じくらい困惑していました。しかし、これは DynamoDB のアーキテクチャを理解するための興味深い方法です。
ケーススタディ1:予期しない書き込みスロットリングの謎
この顧客は私たちのところに来て、彼らのアプリケーションが予期しない書き込みスロットリングを受けていると言いました。ここで一度立ち止まって言うべきことがあります。ここにいる皆さんの中で DynamoDB を使ったことがない人は何人いますか?わかりました、ほとんどの人が使っているんですね、良かった。この顧客は予期しない書き込みスロットリングについて不満を言いました。これは国家的危機でした。このアプリケーションが機能しなければ、このアプリケーションはまだ本番環境に入っていませんでしたが、 文字通り国家的危機になっていたでしょう。彼らは全国規模の世論調査を実施していて、このアプリケーションが機能する必要がありました。
古いシステムがあり、それはレガシー RDBMS を使用していて、そのシステムは今 DynamoDB を使用するために完全に書き直されていました。古いシステムは 600 TPS だけで済みました。その理由については後で説明します。しかし COVID が来て、 人々がカウンターに行くなどを含む古いシステムはもはや起こることができなくなったので、彼らは自分たちでセルフサービスのモバイルアプリケーションを作ろうと言い、そのモバイルアプリケーションは 45,000 TPS をサーブする必要がありました。つまり、約 600 から 45,000 に上がったということで、完全な書き直しが必要でした。
顧客は書き込みスロットリングが発生していると言いました。では、最初に私たちが彼らに尋ねたのは、どのスループットで書き込みスロットリングが発生していますかということでした。800 TPS です。 さて、1分間に17,000個のバスタブ、800 TPS。ここで何か間違っています。それで私たちはそれを掘り下げて、彼らに尋ねました。あなたのアプリケーションは何ですか?それは非常にシンプルなアプリケーションです。このアプリケーションを理解するために、私はこのアプリケーションをほぼ正確に説明しようとしています。理解する最も重要なことは、匿名性がこのアプリケーションで本当に重要だったということです。
では、それを念頭に置いておいてください。ワークフロー自体は非常にシンプルです。彼らは1つのテーブルを読んで、3つのテーブルを書くんです。それだけです。では、これらのテーブルは何でしょうか? 1つ目は national ID テーブルです。左側のやつですね。これは実際のデータではなく、合成データです。匿名性が非常に重要だと言いました。ランダムな ID を持つテーブルがあり、調査自体は2つのテーブルで構成されています。survey テーブルと personally identifiable information です。彼らはデータを分離することに非常に注意を払っています。そこで彼らはこれら2つのランダム化された ID を考え出しました。
1つは PID と呼ばれ、もう1つは SID と呼ばれています。基本的な考え方は、PID が PII テーブルに結びついており、SID が survey テーブルに結びついているということです。では、もし誰かがこれらの1つにアクセスできたとしましょう。ここで機能したかどうか見てみましょう。survey データにアクセスできたとしても、このランダム化された ID ルックアップが必要になるため、personally identifiable information に直接アクセスすることはできません。そして彼らは、それにアクセスできる人が多くないようにしました。ですから、必要に応じて PII を見ることもできますし、survey を見ることもできますが、2つを一緒に結びつけることは決してできません。しかし彼らはさらに一歩進んで、それを national ID に結びつけませんでした。彼らがしたことは、この組み合わせの hash を作成し、低い cardinality の hash を作成しました。つまり、ランダム ID から national ID に移動したとしても、ある数の人々を取得することはできますが、この方向に進むことは決してできません。Jack が survey で何を選んだのか、ということを言うことは決してできません。これがアプリケーション全体の前提でした。ランダム ID、personally identifiable information、survey 情報があり、彼らは 800 TPS でスロットリングしています。
では、アプリケーションは実際に何をしたのでしょうか?全体のフローはどのように機能するのでしょうか?彼らは登録有権者など全員にメールを送ります。旧システムでは、人々は物理的な場所に行き、運転免許証などで身元を証明して、たくさんの質問に答えて、終わりでした。しかし COVID のため、人々が物理的な場所に行く能力がありませんでした。
そこで彼らはこのモバイルアプリケーションを構築しました。アプリ自体は何をするのでしょうか?ランダム ID を生成し、personally identifiable information と survey を記録し、その一方向 hash を national ID テーブルに入れます。シンプルです。1つの読み取り、3つの書き込み。それだけです。ここまで皆さん大丈夫ですか?
では、彼らがどのようにランダム ID を取得し、それが特定のレコードにどのようにマップされるかについての情報をお見せします。 非常にシンプルです。では、このアプリケーションは、こんなにシンプルなのに、どうして書き込みスロットリングを持つことができるのでしょうか?私たちはこれがどのように起こる可能性があるのか、何の方法も見つけることができませんでした。これは洗練された顧客です。彼らはすべての正しいことをしました。高い cardinality キーでテーブルをスケーリングするなど、すべての良いことをしました。そこで私たちはさらに一歩進んで、彼らにスキーマについて教えてもらうよう依頼しました。
もう少し詳しく説明すると、national ID テーブルと random ID テーブルにも GSI があります。 GSI は global secondary index のことです。 GSI の基本的な考え方は、別のアクセスパターンを提供するということです。この場合、AID、つまり anonymous ID を持っていて、national ID を取得したい場合は、この GSI を使用します。または、SID を持っていて PID を取得したい場合は、この GSI を使用します。一方、テーブルの primary key を使用すれば、例えば PID から SID に移動することができます。
これは 1 つの read と 3 つの write を持つシンプルなアプリケーションです。これは絶対に起こっているはずがありません。そこで次に私たちが彼らに聞いたのは、アイテムのサイズはどのくらいかということです。 もしかして 1 メガバイトのアイテムを書き込んでいるから問題が発生しているのではないかと思いました。 いいえ、小さいアイテムです。500 バイト、2 キロバイト、400 バイト。 次の質問は、ID が本当にランダムなのかということでした。なぜなら、それが唯一考えられることだったからです。小さいアイテムと適切にスケールされたテーブルがあり、LSI や他のものがない場合、なぜ throttle が発生するのでしょうか。
そこで ID がランダムなのかを聞いて、この random ID の乱数生成器についてもっと詳しく教えてほしいと言いました。彼らは言いました、それは乱数生成器ではないと。 様々な法定上の理由から、このテーブルは事前に random ID で入力されています。つまり、彼らはこのテーブルを事前に入力しておいて、実行時にすべてのことはこのテーブルをスキャンするだけです。これが random ID を生成するメカニズムです。これが乱数生成器です。 このテーブルは事前に入力されています。彼らは高いカーディナリティと本当にランダムであることを確認しました。random ID を生成するマイクロサービスがあります。それが行うことは、一度に大量の行を読み取ります。おそらく 1000 行のバッチを読み取って、最後に評価されたキーを記録します。その後、ID が必要な場合は、それを提供します。基本的にこれがこのアプリケーションの動作方法です。彼らは高いカーディナリティを確認しました。ちなみに、GSI は non-unique です。 私たちは uniqueness を強制しません。彼らは SID も unique であることを確認しました。それは彼らの法定要件です。
この乱数生成器に何か変なところがあるのですが、私たちには正しく見えました。そこで私たちは、わかりました、いいでしょう、と言いました。しかし、それでもこの乱数生成器についていくつかの疑いが残っていました。そこで次の質問は、この write throttling はどこで発生しているのかということです。明らかに、write throttling は 2 キロバイトの write があるテーブルで発生していると思いました。いいえ、それは小さい方の write、500 バイトの write です。 ここまでで分かっていることは、彼らは 800 TPS で throttle されているということです。60 日後には、45,000 TPS に到達する必要があります。では、ここにいる誰か、何が問題なのか考えがある人はいますか。手を上げてください。彼らが PII テーブルで約 800 TPS で throttle されていると思う人。まだ手が上がっていないようです。いいですね。私たちも全く同じ状況でした。
ハッシュベースのパーティショニングと決定論的ハッシュの落とし穴
私たちは困惑していました。なぜこんなことが起こっているのか理解できませんでした。 では、私たちがどのようにスケールするかを説明します。水平方向にスケールします。テーブルをパーティション化します。partition key を提供すれば、私たちがパーティション化します。 基本的にはハッシュベースのパーティショニングです。
テーブルを作成する際、私たちはテーブルの名前とそのテーブルの主キーが何かをお聞きします 。それだけです。Global Secondary Index(GSI)についても同じことが言えます。私たちはそれにどのように料金を払うのかを知る必要があります。ただし、ここに注目してください。これはユニークではありません 。これが GSI とテーブルの唯一の違いです。では、こちらが NationalID テーブルです。彼らがこのデータを入力したいとき、私たちは何をするでしょうか? ハッシュを計算します。このプレゼンテーション全体を通じて、私はハッシュを示しています。これらは実際の DynamoDB ハッシュではなく、単なる MD5 です。ですから、ハッシュを計算してから、そのデータをハッシュ値に基づいてソートします。そしてハッシュ値でソートした後 、区切りを作成し、それらをパーティションと呼びます。これが基本的に DynamoDB がどのように機能するかです。ハッシュベースのパーティショニングによる水平スケーリング、非常にシンプルです。
パーティションはハッシュの連続した範囲です。パーティションキーのハッシュを計算し、ハッシュに基づいてソートし、連続した範囲がストレージノードに保存するパーティションになります。これが基本的に私たちの仕組みです。私たちが使用するハッシュにはいくつかの特性があります。 もちろん、高速なハッシュである必要があります。私たちはこれを非常に高い頻度で行うため、ハッシュは効率的に計算される必要があります。ハッシュも均等である必要があります。つまり、他のものよりも高い頻度で同じ値を生成するハッシュを持つことはできません。
私たちのハッシュのもう 2 つの特性は、決定論的である必要があり、アバランシュプロパティと呼ばれるものを持つ必要があるということです。 決定論的ハッシュは基本的に、どのテーブルであろうと、誰のユーザーであろうと、X が Y に等しい場合、X のハッシュは Y のハッシュに等しいということを意味します。すべてのテーブルまたはすべてのユーザーで同じである必要はありません。それは単に私たちがそれを実装した方法です。私が言及したもう 1 つの特性はアバランシュで、これは基本的に、ある値を持っていて、その値に小さな変更を加えた場合、ハッシュに大きく予測不可能な変更が見られるべきだということを意味します。
値に非常に小さな変更を加えていることに注目してください。そしてハッシュに非常に大きな変更が見られます。これらが私たちが使用するハッシュ関数の特性です。 これは 10 年以上にわたってうまく機能しており、このハッシュ関数に問題が生じたことはありません。こちらが RandomID テーブルが実際にどのように見えるかです。PiD と SiD があります。ハッシュ値を計算し、ハッシュ値に基づいてデータをソートします 。そしてそれをパーティションに保存します。これが基本的に DynamoDB が毎日行っていることです。
顧客がリクエストを行うとき、彼らはスキャンを実行し、スキャンはハッシュの順序でテーブルを走査します。その後、テーブルの実際の属性を含む最後に評価されたキーを返します。ですから、次回戻ってきてリクエストを行い、開始点を指定すると、同じ場所からスキャンを続行します。これが基本的にスキャンの仕組みです。誰か、何が問題になっているかについてアイデアを持っていますか?では、乱数生成器がどのように機能しているかを見てみましょう。彼らはテーブルをスキャンしています。彼らが見ているように見えるのはこのデータです。 そのデータを見てみましょう。これが乱数生成器が返しているものです。私には完全にランダムに見えます。
一見するとランダムに見えるかもしれませんが、実はハッシュの順序で並んでいるので全くランダムではないんです。それで彼らは Survey テーブルを書き込みます。これはスロットリングの原因になっていたテーブルではありません。 RandomID テーブルからデータを読み込んで SiD に書き込んでいるので、あちこちに散らばることになります。これは本当に良いことなんです。なぜなら、これが彼らが見ることになる正しいパターンだからです。これが水平スケーリングを実現する方法なんです。 テーブルを、この場合は 8 つのパーティションに分割して、継続的に書き込みを行いますが、トラフィックが複数のパーティション全体に分散されます。もう一つの方を見てみましょう。 PiD の値で読み込みを行うと、暗黙的にハッシュ順で取得することになります。
したがって、データは同じキーにある PII テーブルに書き込まれます。つまり、書き込みがテーブル全体にランダムに分散されていないんです。ランダム ID の最初のブロックについては、1 つのパーティションを集中的に叩いて、次のパーティションに切り替えてそのパーティションを集中的に叩く、という具合です。 つまり、水平スケーリングのメリットが得られていないわけです。これの理由は、もちろん、私たちの決定論的ハッシュの意図しない結果なんです。どのテーブルであろうと、どのユーザーであろうと、どのリージョンであろうと、ハッシュ値は同じなんです。
問題の解決策とスキーマモデリングの新機能
ただし、これを修正するつもりです。ですから、これに依存しないでください。後で痛い目に遭う可能性があります。テーブルをスキャンしてクエリ操作を実行し、アイテムコレクション内で複数のアイテムを取得する場合、データはあなたにはランダムに見えるかもしれませんが、ソート済みのハッシュ順で返されてくることを覚えておいてください。 では、これをどうやって修正するのか。最初に私たちが顧客に言ったことは、本当のランダム数生成器を用意してくださいということです。彼らの答えは、いや、それはできないということでした。ランダム数を事前に入力する必要があるという法定要件があるんです。
これが機能する必要があるまで 60 日しかなく、彼らはアプリケーションに大きな変更を加えることも望んでいませんでした。それで、私の同僚の一人がこんな賢いアイデアを思いつきました。彼は言いました。本当に必要なのは、このテーブルを読み続けることだと。これがあなたのランダム数生成器です。それは変えないけれど、PII テーブルへの書き込みトラフィックを生成して分散させたいんだと。 1 つのパーティションを集中的に叩いて、次のパーティションを集中的に叩く、というようなことにはしたくないんです。 それで私たちが思いついたのは、別のテーブルに書き込むときに、ID の前に 2 文字を付けてはどうかということです。例えば、TX をその前に付けるとしましょう。 その理由は、小さな変更を加えるだけでハッシュ値が大きく変わるからです。これでテーブルを読み進むにつれて、トラフィックが PII テーブル全体に分散されるようになります。 これで複数のパーティション全体に負荷が分散されるようになり、良い状態に戻りました。
このチームは 45,000 TPS でシステムをベンチマークするよう求められました。 彼らは喜んで 90,000 でベンチマークしたと思いますし、調査は何の問題もなく進みました。覚えておくべきことは、スケーリングの方法はハッシュパーティショニングを通じたものだということです。例えば GSI 上のアイテムのようなトラフィックがある場合、テーブル内に GSI に対して同じ値を持つ大量のアイテムがあると、その GSI でのパフォーマンスが低下することになります。 高いカーディナリティと一意性が本当に重要です。1 つのテーブルから読み込んで、同じキーを共有する別のテーブルに書き込むような状況にある場合、私たちがこれを修正するまで、この問題の影響を受ける可能性があることを覚えておいてください。修正には時間がかかるでしょうが、かなり早い時期に修正できることを期待しています。
ベンチマークは成功しました。調査が実施されて、すべてが上手くいっていました。それが最初のものです。 これが起こった時、私たちは本当にこの問題に気づいていませんでした。しかし今、この問題を知ってしまった以上、これはマーフィーの法則というやつです。問題があることを知ると、それに遭遇するようになるんです。数週間ごとに、私たちは顧客からの報告を聞きます。「ああもう大変だ、火事だ、危機的状況だ、アプリケーションがスロットリングされている」と。 結局のところ、同じ問題なんです。ですから、アプリケーションを構築しているのであれば、これを念頭に置いてください。これはあなたに眠れない夜をもたらす可能性があるパターンです。
ですから、皆さんにとって重要なポイントは、consistent hashing があるということです。これはあなたにとって問題を引き起こす可能性があります。これが DynamoDB が今日機能する方法です。 うまくいけば、すぐに修正されるでしょう。そして、おそらく、確実に週に数回、あるいは数週間ごとに、私たちはこれについて聞きます。avalanche のパワーを活用して小さな変更を加えることができれば、あなたにとって簡単に修正できます。 ですから、一つのテーブルを読んでいる時に、別のテーブルに書き込む場合、同じキー値を選ばないでください。そうすればこの問題は発生しません。スロットリングのデバッグは非常に難しかったです。
私たちが初めてこの問題に遭遇したのは、約 4 年前のことです。 CloudWatch Contributor Insights は文字通り唯一の方法ですが、非常に高額でした。私たちが顧客に CloudWatch Contributor Insights を有効にしたと伝えた時、彼らは言いました。 「高すぎます、私たちにはできません」と。問題が発生した後に有効にすることはできません。問題が発生している時に有効にしておく必要があります。
ですから、私たちは throttled keys only を導入しました。これはスロットリングが発生している時だけログを記録するということで、かなり低い料金で済みます。私たちが行ったもう一つのことは、 スロットリングが発生した時に、enhanced error codes を返すようにしたことです。これらは backward-compatible なので、アプリケーションに変更を加える必要はありません。例外は正確なリソースと理由を特定します。書き込みスロットリングの場合、GSI がバックプレッシャーを生成している場合、時々スロットリングされることがあります。そして、どの GSI かも特定してくれます。ですから、スロットリングに直面した場合、これを念頭に置いてください。 CloudWatch Contributor Insights には、これで 10 個の新しいメトリクスがあります。
簡単に触れておきたいことが一つあります。過去に partition key と sort key について言及しました。 約 1 週間前までは、partition key と sort key は単一の属性でした。つまり、複雑なスキーマがあった場合、モデル化が少し難しくなったということです。 ですから、顧客の中には、customer ID と order ID を 一緒に入れて、sort key に対して begins with と contains を使うなど、非常にハッキーな回避策をする必要があった人たちがいました。
また、顧客 ID をキーに持たせて、それを属性として保存したいという場合、問題があります。ストレージに対して二重に支払うことになるのです。 この二つは同期がずれる可能性があり、冗長性の問題は常に、この二つの間に矛盾が生じる可能性があるということです。正確性の問題があるのです。 その代金を払いたくなくて、冗長性を避けたいとなると、時間とともにスキーマを進化させるのが難しくなります。例えば別の GSI を構築する必要があり、order ID を使いたいとなると、今度はこのキーの途中から引き出してバックフィルする必要があります。それが面倒だったわけです。
ですから、一週間前、私たちはこれをリリースしました。パーティションキーとソートキーに最大 4 つの属性を持たせることができるようになったのです。 これによって、データモデリングが大幅に簡単になります。現在のところ、これは GSI のみでサポートされており、将来的にはテーブルに対しても行うかどうかを検討します。リンクは私たちのドキュメントへのものです。もちろん、Alex の LinkedIn の投稿を見たければ、それも見ることができます。また、スキーマモデリング用の MCP サポートも追加されました。ですから、興味があれば、非常に優れたスキーマモデリングアドバイザーがあり、これらの新しい機能を活用することができます。では、次のものに進みましょう。これも同様で、これもまた顧客から報告された問題です。
ケーススタディ2:高トラフィック時に低レイテンシー、低トラフィック時に高レイテンシーという逆説
これは私たちが内部で使用しているツールのビューです。 サポートに連絡すると、彼らが求める情報の一つが subscriber ID で、その subscriber ID があれば、アプリケーションのこのようなパフォーマンスメトリクスを見ることができます。これは実際の顧客の 7 日間のデータです。読み取りと書き込みの左側が読み取り、右側が書き込みのトラフィック履歴を示す 7 日間分のデータです。 ピークからトラフに至るまでが約 2,000 倍です。
この特定のアプリケーションは、1 日に 1 回実行されるジョブを実行しており、それが 1 日の残りの時間と比較してかなり高いレートを駆動しています。 ですから、この顧客のアプリケーションは、アプリケーションが想定通りに動作する方法です。これは異常ではなく、文字通り彼らが望んでいることです。これは継続的なインタラクティブなワークロードで、低トラフィック期間です。 そして、これらはスパイクで、ワークロードのバッチ部分です。
さて、このアプリケーションについて奇妙な点があります。 トラフィックが低いとき、レイテンシーは高く、変動します。トラフィックが高いとき、レイテンシーは低く、非常に許容可能で、予測可能な低レイテンシーのフラットラインです。これは完全に直感に反しています。通常、高トラフィックは高レイテンシーを意味すると想定するでしょうが、そうではありません。高トラフィックは非常に良好なレイテンシーをもたらし、一方、低トラフィックは恐ろしいレイテンシーをもたらします。ここでこれに遭遇した人はいますか?このパターンを見たことがある人はいますか?
このアプリケーションを実際に経験したお客様がいるんですが、その方がここにいらっしゃいます。これは文字通り彼らのアプリケーションからのデータです。これが平均レイテンシーです。ご興味があれば、私たちは他のメトリクスも保存しています。P90 と P99 パーセンタイルも保存しているんです。 これが 90 番目のパーセンタイルなんですが、全く同じパターンを示しています。何が起きているのかを理解するために、私たちはシミュレーターを構築して、ラボでこれを再現することができました。高いトラフィックは低い許容レイテンシーをもたらし、一方で低いトラフィックは恐ろしいレイテンシーをもたらしました。これは奇妙な状況です。
このアプリケーションが何をしているのかを理解するために、これがリクエストタイプです。get item と put item です。 翌日も同じ動作を示しました。何が悪いのか、誰か考えがありますか?何が起きているのか、誰か分かりますか?私たちは彼らのアプリケーションがどのようなものかを聞きました。 これは私たちが構築したシミュレーターの説明というより、彼らは継続的なトラフィックとバッチトラフィックを持っています。バッチが高いトラフィックを駆動し、彼らはインスタンスのフリートを持っています。私たちのシミュレーションでは、150 台のホストが DynamoDB を通じてトラフィックを駆動していて、これは非常にシンプルです。何が悪い可能性があるのでしょうか?高いトラフィックで良いレイテンシーを持ちながら、低いトラフィックで恐ろしいレイテンシーを持つという状況をどうして持つことができるのでしょうか?
DynamoDBアーキテクチャとキャッシュの重要性:長寿命接続がもたらすパフォーマンス向上
これがなぜ起きるのかを理解するために、DynamoDB のアーキテクチャを掘り下げてみましょう。 アプリケーションは SDK を通じて私たちに接続し、パブリックエンドポイントを解決して、ロードバランサーにポイントされます。 ロードバランサーの背後に、そしてロードバランサーは複数のアベイラビリティーゾーンにあります。私たちはリクエストルーターを持っています。あなたが行うすべてのリクエストは個別に認証と認可が必要です。私たちはあなたが本人であることを確認し、あなたの SigV4 署名が正しいことを確認し、あなたがしようとしていることが許可されていることを確認します。すべてのリクエストがこの検証を必要とします。
そのために、私たちはいくつかのメタデータを検索し、あなたがプロビジョニングされた制限を超えている場合、またはあなたのテーブルがスケールできない場合、あなたをレート制限します。あなたのデータは実際にはストレージノードに保存されており、リクエストルーターの仕事は、どのストレージノードにリクエストを送信すべきかを判断することです。 ストレージノードの下では、すべてのデータは保存時に暗号化されているため、復号化キーを取得するために KMS に行く必要があります。ストレージノードにもレート制限があります。これらは私たちが前に議論したスロットリング制限です。これをどのようなスケールで行う必要があるのでしょうか?1 分あたり 17,000 リクエストですね?ですから、私たちはこれらすべてのコンポーネントで広範なキャッシングを使用しています。
リクエストルーターはメタデータとアイデンティティ情報のキャッシュを保持しています。あなたのアプリケーションからの TCP 接続はリクエストルーターに行きます。同じ接続を何度も使用し続ける限り、このキャッシュの利点を得ることができます。ここに 1 つのリクエストを送信して、そこに 1 つのリクエストを送信すると、キャッシュの利点を得られないかもしれません。 私たちはこれを 1 秒あたり数億回行っており、これを最適化しないことは物理的に良いことではありません。
毎回再接続するのは、TCP ソケットのセットアップと TLS 全体を経由する必要があるため、物理的に良くありません。 もちろん、認証とその認証のキャッシングがあり、これらを念頭に置く必要があります。使用するすべてのメタデータはストレージノード上にあります。 暗号化キーを扱う必要があり、アプリケーション内には接続プールがあります。 元の場所に戻ると、同じリクエストルーターに何度も到達できれば、これらのキャッシュの利点が得られます。そうでなければ、得られません。
可能な限り、長寿命接続を使用するようにしてください。 この特定のアプリケーションの場合、彼らが抱えていた問題はキャッシュの利点を得られていなかったということです。 彼らの大規模なトラフィックは大量のホストを使用していて、継続的なトラフィックを行っているときに、バッチが実行されていないときは、ほぼ 2,000 倍少ないトラフィックでした。 私たちの仮説は、彼ら側に関わるホストの数が多いため、キャッシュの利点を得られていないということでした。
そこで、彼らに何台のホストを持っているのかを尋ねました。シミュレーションの目的で、私は 150 台を使用しました。顧客は数千個のコンテナを持っていると言いました。 バルク取り込みは 20,000 TPS で、継続的なものは 10 でした。これらが 2,000 倍の差をもたらした数字です。 これらの数千のホストまたは数千のコンテナはこのようにプロビジョニングされています。なぜなら、それらは静的に安定しているからです。 静的に安定というのは基本的に、コントロールプレーンの変更を必要とせずに、どのようなトラフィックでも引き続きサービスを提供できるようにしたいということです。時間内にスケールアップできない場合、トラフィックをサービスできません。したがって、常にピークにスケールされています。
それが要件です。おそらく、彼らは 1 日に 1 回だけではなく、いつでもバルク取り込みを受け入れたいと考えています。 1 つのオプションは、継続的なインタラクティブ時間中にホストを削減することです。これは彼らが喜んでやることではなく、また彼らは規制業界にいるため、実際に試すのに時間がかかります。 私たちのシミュレーションはこのようなものでした。低レイテンシーの高トラフィックと、高くて変動するレイテンシーの低トラフィックです。これをラボで完璧に再現することができました。
私たちが行ったことは、継続的なインタラクティブトラフィックが少数のホストにのみ流れるように再構成することでした。 これが、フラットラインに再構成した時点です。なぜなら、今では必要なすべてのキャッシュの利点を得ているからです。 これが彼らに良いパフォーマンスを与える構成です。さて、これらは彼らがお金を節約したい場合にできることの 2 つです。低トラフィックで実行して、より高いトラフィックがあるときにスケールアップします。しかし、これは静的に安定していません。
auto-scaling でコストを削減できるとしても、アプリケーションが bimodal になってしまいます。彼らの設定は正しいと思います。常に同じ数のホストで実行するということです。 ただし、私たちが彼らに推奨したのは、低トラフィックを少数のホストに送信して、すべてのホストに送信しないようにすべきだということです。私たちのシミュレーションでは、それが有益であることを示しました。
まとめとして、私は数年間 database を使ったアプリケーションを構築してきましたが、database が実際にどのように動作するかを理解することは常に重要です。database がどのように動作するかを知らないということは、アプリケーションを構築する能力が大幅に低下することを意味します。内部で何が起こっているかを理解することは本当に重要です。 同様に、誰でもハードウェアストアに行ってペンキを買うことができますが、アートを思いつくには、ある程度の思考と人間の創造性が必要です。お客様が構築しているもの、皆さんが構築しているものは、本当に難しく、複雑なアプリケーションであり、かなりの思考が必要です。ですから、私たちはこれらのアプリケーションを構築するのをお手伝いするためにここにいます。そして、フィードバックをお待ちしています。
※ こちらの記事は Amazon Bedrock を利用し、元動画の情報をできる限り維持しつつ自動で作成しています。


































































































































Discussion