Amazon Web Services ブログ
Redis 用 Amazon ElastiCache を使用してリアルタイムの販売分析ダッシュボードを構築する方法
Amazon ElastiCache について説明すると、ほとんどの場合、読み取り負荷の高いデータベースワークロードのパフォーマンスを向上させるという文脈になります。リードスルーまたはライトスルーのパターンを採用するようにアプリケーションを更新し、キャッシュ内のデータを最新に保ち、データベースの負担を軽減します。この文脈で使用すると、ElastiCache はデータをメモリにキャッシュして大量のワークロードを高速化し、ミリ秒未満のデータ取得パフォーマンスを実現します。さらに、Redis 用 Amazon ElastiCache は、マルチ AZ 設定の自動フェイルオーバーにより、ワークロードの可用性とフォールトトレランスを向上させます。
ただし、ElastiCache は、ワークロードをより効率的にするだけでなく、新しい機能を提供するなど他にも多くの利点をもたらすことができます。この記事では、Redis 用 ElastiCache で構築されたリアルタイムの販売分析ダッシュボードの文脈で、こうした機能のいくつかを検討します。
この例で使用されているダッシュボードのコードとサンプルアーキテクチャは、GitHubの aws-elasticache-retail-dashboard リポジトリから入手できます。
ダッシュボードの指標
このダッシュボードは、広範な製品カタログを持つ大量の電子商取引サイトについて、ほぼリアルタイムの指標を提供します。リレーショナルデータベースを使用してこうしたダッシュボードを構築するには、リソースを集中的に使用するクエリの複雑なセットが必要です。代わりに、少数の Redis コマンドを使用してこのデータを追跡します。
このダッシュボードは、5 つの主要な一般的販売指標に焦点を当てています。
毎日の注文数
まず、簡単な指標である、毎日の注文数から始めます。注文を受け取るたびに、注文数を 1 つ増やします。操作は高速でアトミックなので、リレーショナルデータベースのテーブルの行数を数える必要はありません。毎日、新しいキーを作成し、Redis は初期値 0 のキーを作成します。ダッシュボードは当日の注文数にのみ関係しています (履歴データは後で取り上げます)。
2018 年 3 月 11 日の注文数を増やすには、指定したキーに保存されている整数値をインクリメントする、Redis INCR
操作を使用します。キーが存在しない場合は、操作が実行される前に値が 0 に設定されます。
これで、次のように整数形式の値を取得できます。
当日販売された一意の商品の数
毎日の注文数をカウントしたので、次はそれらの注文で販売されている商品に関するデータを収集しましょう。まず、毎日販売されている一意の商品の数 (SKU または一意の ID による) を追跡しましょう。注文数の指標と同様に、同じ結果を作成する SQL クエリ (例、select count(*) from orders
) を書くこともできます。ただし、この目的のために ElastiCache を使用するよりも複雑であり、パフォーマンスが低下します。
Redis の Set データ構造を使用すると、一意性のカウントが容易になります。Set は members と呼ばれる一意の文字列のリストです。注文を受け取るたびに、次のように、各商品の SKU をその順序で一意の商品セットに追加します。
Set に商品を追加することに加えて、ハウスキーピングのために EXPIRE
コマンドも使用します。EXPIRE
コマンドは、キーとデータが Redis での保存で期限切れとなるまでの秒数を取得します。ここでは、有効期限を 1 週間として、商品を購入するたびに EXPIRE
を呼び出します。
ダッシュボードでは、SCARD
を使用して、購入された一意の商品の整数でのカウントを取得できます。
リーダーボード
ダッシュボードの一部として、最も購入された商品のランキングも常時表示したいと考えています。リーダーボードは、Sorted Set データ構造で構築された Redis の一般的なユースケースです。 Sorted Set は、members と呼ばれる非繰り返し文字列のリストであり、セット内のすべてのメンバーはスコアに関連付けられています。このリーダーボードのスコアは、販売された商品 (メンバー) の合計数です。 セットのメンバーはすばやく追加、削除、更新することができます— 時間の複雑さは O(log n)
であり、ここで n はセット内の商品の数です。
ID が 123456789 である 2 つの商品の注文が入力されると、次のようにリーダーボードのエントリを増やすことができます。
ZREVRANGE
を使用して先頭の要素を取得することができます。ここでは、上位 10 を取得します。
最後に購入された製品
常時のリーダーボードが有用であるのと同様に、当社のビジネスでは販売されている製品のライブフィードにも関心があります。 この場合、Redis の List データ構造を使用して、最近販売された 100 商品のリストを追跡します (Unix のタイムスタンプをスコアとして使用して、Sorted Set を使用して同じことを実現できることに注意してください)。
次の例では、商品の SKU を、最新の製品キーに保存されているリストの先頭にプッシュします。プッシュを実行する前にリストが存在しない場合は、空のリストが作成されます。それぞれの新しい商品をリストにプッシュした後、LTRIM
を使用してリストの長さを合計 100 商品に調整します。
最後に販売された 10 の商品を先頭から取得するには、LRANGE
を使用します。
たとえば、商品のリストにページ割りを追加する場合は、開始インデックス 10 と終了インデックス 19 を指定して、次の 10 の商品を取得できます。
過去の売上収益
最後に、売上収益を見ることなく、売上ダッシュボードは完成しません。この場合、当社のビジネスではダッシュボードで 1 時間毎に追跡した 1 週間分の履歴データを表示する必要があります。ここでのアプローチでは、データがある日付と収益データ自体を 2 つの別々のデータ構造で追跡します。
まず、収益データを現在の日付で Redis にプッシュするたびに Sorted Set を更新します。ここで Sorted Set を使用する利点は、各メンバーが一意であることです。メンバーのスコアを常にゼロに設定することにも注意してください。スコアが結合されている場合、結果はメンバーの値でソートされて返されます。したがって、応答は日付によって昇順にソートされます。また、ZREMRANGEBYRANK
コマンドを使用して 7 日分のデータだけを保存することで、不要なデータを取り除くこともできます。
ソートされたセットに現在の日付を追加した後、Redis Hash で時間単位の収益を増加させます。ハッシュは、キー (現在の時間) と値 (収益) の間のマッピングを保存するために使用されます。日付ごとに、7 日後に期限切れとなるデータのハッシュを別々に保持します。
週全体の売上データを取得することは、これまでの例よりもやや複雑です。ここでは、Sorted Set のデータを持つ日付のリストを最初に取得し、各日付について繰り返し処理し、Hash から時間単位の収益を取得する必要があります。これらの日のうちの 1 つ (2018 年 3 月 11 日または “20180311”) の過去の週の日付リストと収益データを取得するには、Redis コマンドは次のようになります。
実装は言語によって若干異なりますが、次の擬似コードは 1 週間分の収益データを収集する方法を示しています。
動作する Node.js の例については、GitHub リポジトリで提供されているサンプルコードを確認してください。
サンプルアーキテクチャ
この販売ダッシュボードの機能を示すため、GitHub の aws-elasticache-retail-dashboard リポジトリにサンプルアーキテクチャを提供します。サンプルの目的のために、注文データを AWS Lambda 関数に渡す Amazon Kinesis を使用して注文を取り込みます。 現実のシナリオでは、ダッシュボードや他のシステムへの配信を調整するために、おそらく AWS Step Functions と組み合わされる注文処理システムによって注文処理が行われます。
Node.js で書かれている Lambda 関数 (ProcessorFunction
) は、オープンソースライブラリ (多種多様なプラットフォームで同様の Redis クライアントライブラリが存在しますが、ioredis) を使用して該当するデータを ElastiCache Redis インスタンスにプッシュします。コードを確認する場合は、関数が前述のコマンドと同じコマンドを実行することに注意してください。
このサンプルでは、ダッシュボードのリアルタイム性を有効にするために AWS Fargate を使用して、(1) ウェブソケット経由で接続するクライアントアプリケーション (Vue.js で構築)、(2) バックエンドの Node.js アプリケーションという 2 つのサービスを実行します。バックエンドアプリケーションでは、Redis のパブリッシュ/サブスクライブ (pub/sub) 機能を使用して更新を通知し、ダッシュボードにプッシュします。このアプローチで、ダッシュボードは Lambda 関数によって更新された最新の販売指標を正確に反映することができます。
サンプルデータの生成を含む、サンプルアーキテクチャーのデプロイメントの詳細については、GitHub リポジトリを参照してください。
Pub/Sub
前述の機能以外に、Redis は pub/sub 機能も提供しています。この機能を使用して、チャットなどのプッシュされる更新を必要とするアプリケーションに加えて、このタイプのほぼリアルタイムのシステムを推進することができます。昨年、同僚の一人が、Redis を使用してチャットベースのアプリケーションを構築するアプローチについて説明しました。
監視とパフォーマンス
ここではサイジングとパフォーマンスの詳細を掘り下げませんでしたが、効果的な監視は、パフォーマンスが高く、費用対効果が高いソリューションをデプロイするうえで重要です。ElastiCache は Amazon CloudWatch と統合され、クラスター全体とそれを構成するインスタンスのパフォーマンスを把握します。サンプルダッシュボードでは、1 つのレプリカで t2.medium を使用しています。ただし、本稼働システムでは、ストレージを増やしパフォーマンスを向上させるために、より大きなインスタンスタイプを使用でき、追加のレプリカを使用して冗長性と可用性をさらに強化することができます。
ElastiCache クラスターを実行している場合、クラスターのサイズを適正化し、パフォーマンスを測定するのに以下の指標が便利です。
- CPUUtilization: Redis を実行しているインスタンスの CPU 使用率。
- FreeableMemory: ホストで使用可能な空きメモリの量。
- NetworkBytesOut: ホストがネットワークから読み取ったバイト数。
- NetworkBytesIn: ホストがネットワークに書き込んだバイト数。
- SwapUsage: ホスト上で使用されるスワップの量。
さらに、以下の Redis 固有の指標も役立ちます。
- BytesUsedForCache: Redis が割り当てる合計バイト数。
- EngineCPUUtilization: Redis はシングルスレッドなので、これはエンジンが動作しているコアの CPU 使用率です。
- CurrConnections: 現在の Redis への接続数。
Redis クラスターのサイジングの詳細については、この記事の範囲を超えていますが、これらの指標を使用すると、クラスターのサイズを適切に調整できます。ElastiCache を拡大または縮小させて、ニーズに適合させることができます。
まとめ
シンプルなキャッシングの価値以外のユースケースで Amazon ElastiCache を使用することについて簡単にご理解いただければ幸いです。完全マネージド型の Redis エンジンを使用してアプリケーションの複雑なロジックを簡素化できるだけでなく、アプリケーションのパフォーマンスを向上させ、コストを削減することもできます。
1 年間、毎月 750 時間の cache.t2.micro ノードの無料使用が含まれている AWS 無料利用枠で、ElastiCache を使い始めましょう。
著者について
Josh Kahn は、アマゾン ウェブ サービスのソリューションアーキテクトです。 彼は、AWS を使用している場合にソリューションの価値を向上させる手助けとなるために、AWS の顧客と協力してデータベースプロジェクトの指導や技術支援を行っています。
Mike Gillespie は、アマゾン ウェブ サービスのソリューションアーキテクトです。 彼は、AWS を使用している場合にソリューションの価値を向上させる手助けとなるために、AWS の顧客と協力してデータベースプロジェクトの指導や技術支援を行っています。