Redis
 Computer >> コンピューター >  >> プログラミング >> Redis

リアルタイム緊急対応システム:Upstash、Redis、QStash の活用

今日の記事では、Upstash を活用して、Redis を使用して国の避難所マップに関する情報を安全に保存およびアクセスし、QStash 経由でデータベースをリアルタイムで更新する方法について説明します。

はじめに

現在の世界情勢では、自然災害や軍事的脅威がますます蔓延しています。社会サービス分野におけるデジタル化の必要性も同様です。

AMBER アラートなどの緊急放送システムから、新型コロナウイルス感染症追跡アプリや SOS システムに至るまで、国に影響を与えるあらゆる種類の危険なシナリオに対応するために、幅広いテクノロジーが使用されているのを私たちは目にしてきました。

ここでは、Redis とサーバーレス ワークロードが、市民が最も近い地下壕を見つけられるようにすると同時に、利用可能な容量、機能 (障害者施設など)、およびリソース (水、電気、医薬品など) について情報を提供するリアルタイム緊急対応システムの構築において、どのように重要な役割を果たすことができるかを見ていきます。

リアルタイム緊急対応システム:Upstash、Redis、QStash の活用 プロジェクト Cloud4 の提供

なぜサーバーレスなのか?

いわゆるサーバーレスの概念は、ここ数年開発者の間で普及してきました。このアーキテクチャに従うことを選択するスタートアップ企業の数が増加し、大企業での採用も増加しています。

特に国家主体について話す場合、迅速な開発環境と自動管理サービスにより、緊急対応システム構築の複雑さとオーバーヘッドを大幅に軽減できます。他に 2 つの要素も考慮する必要があります。

<オル>
  • 予算 :国が新たな災害に見舞われなかった場合、意思決定の役割にある人は、未使用のコンピューティング能力に対する支払いを承認できるでしょうか?そうは思えません。
  • トラフィックの急増 :警報が作動し、何百万人もの人々が最寄りの避難所を探すために Web プラットフォームにアクセスしたと想像してください。 REST API はこの突然の rps(リクエスト/秒) の増加をどのように処理しますか?重要なリアルタイム コンポーネントについてはどうですか?
  • このさまざまな質問はすべて、Upstash や Ably のような真のサーバーレス プラットフォームを使用して、自動的にスケールし、使用しているリソースに対してのみ課金される負荷の高いサーバーを強化することで解決できます。

    Redis を使用する理由

    私たちのプロジェクトのデータ要件には、可能な限り最高の速度で実行する必要があるさまざまなアルゴリズム操作が含まれます。避難所の情報を表す基本的なデータ構造から、その場所で利用可能な情報をさまざまな基準で並べ替える簡単な方法に至るまで、Redis を使用すると、NoSQL データベースの柔軟性を維持しながら、開発を簡素化して加速するためのさまざまな機能も提供できます。

    QStash を選ぶ理由

    従来のメッセージ キューは、イベント ドリブン システムを構築する確実な方法を提供しますが、注意点があります。そのほとんどは、AMPQ などのステートフル プロトコルに完全に依存しているため、サーバーレス機能のような短時間実行環境で使用する準備ができていません。

    QStash は、このような環境で通常使用されるステートレス プロトコルである HTTP を使用してリクエストを行うことができるようにすることで、この問題を解決します。これを Webhook と組み合わせることで、データベースとの間でデータを更新およびフェッチするためのリアルタイム パイプラインを作成できます。

    要件

    追伸 .:サンプルを確認したいだけの場合は、要件とセットアップのセクションをスキップしてください。それらは、私たちが何をどのように使用しているかを示すことを目的としています。

    この種のシステムを自分で構築したい場合は、次のものが必要になります。

    • Upstash アカウント。このアカウントから Redis データベースを作成し、QStash エンドポイントまたはトピックを使用します。
    • Ably アカウントと Webhook 統合のセットアップ
    • Next.js プロジェクト;
    • ローカル リクエストをインターネットで利用可能な URL にプロキシする場合は、ngrok などのトンネリング サービスを使用します。
    • 要求されたライブラリをサポートする任意のパッケージ マネージャー。この記事では npm を使用しますが、必須ではありません。

    注意 :この記事では、アプリケーションのアーキテクチャのコンテキストで前述のテクノロジの使用を実証するために、いくつかの基本的な概念実証サンプルを提供します。指定されたコードは本番環境に対応していないため、読みやすいように簡略化および短縮されています。導入する場合は、必ず必要な変更を行ってください(例外処理、セキュリティなど)。

    セットアップ

    サーバーレス機能

    Next.js のエッジ API ルートを使用して、ユーザーの場所に近い場所でサーバーレス ワークロードを実行します。

    Next.js プロジェクトを作成するには、npx create-next-app@latest <your-app-name> を実行します。 親ディレクトリ内。その後、npm run dev を実行できます。 開発サーバーを起動するには、npm run build 製品バンドルと npm run start を作成します。 実稼働サーバーを起動します。

    Next.js は、デフォルトとして API ルートのノード環境を使用します。これは 2 つの方法で変更できます。

    <オル>
  • ルートごとのアプローチ。次のエクスポートを目的のルートに追加します:
    export const config = {
     runtime: "experimental-edge",
    };
  • グローバルなアプローチ。 エッジを作るには デフォルトのランタイムの場合は、次の行を next.config,js ファイルに追加します:
    const nextConfig = {
     // ...
     experimental: {
     runtime: "experimental-edge",
     },
     // ...
    };
  • アップスタッシュ

    Upstash プロバイダを作成するには、このガイドに従ってください。

    QStash レシーバー ルートを設定するには、このガイドに従ってください。Ably では、Webhook メッセージのエンコーディングに JSON と MessagePack の 2 つのオプションが提供されていることに注意してください。前者を使用する場合は、潜在的な暗号化互換性の問題に対処するために、JWT の代わりに認証ヘッダーを使用する必要がある場合があります。簡単にするために、ここでは JSON を使用します。

    必ず

    リアルタイム機能については、Ably のプロトコルを使用します。可能な場合は、デフォルトで WebSocket が使用されます。開始するには、このガイドに従ってください。Next.js を使用しているため、@ively-labs/react-hooks npm パッケージを確認してください。

    また、QStash URL を指すように Webhook 統合を設定し、必要なヘッダーを追加する必要があります。

    本番環境に移行する場合は、認証とセキュリティも確認してください。

    オプション:ローカル トンネリング

    このガイドに従って、ngrok の使用を開始してください

    アーキテクチャ

    フロー

    アプリケーションのフローをよりよく理解するために、次の図を見てみましょう (excalidraw.com で作成)。

    リアルタイム緊急対応システム:Upstash、Redis、QStash の活用

    ご覧のとおり、2 種類のユーザーを定義しました。

    <オル>
  • 国民 、避難所や場所の情報にアクセスでき、地下壕に行く意思を表明できる人
  • 管理者 、バンカーの物流データを変更し、空き状況を変更できる人(たとえば、人や家族がその場所に到着したことを確認する)
  • フロントエンドとバックエンドを可能な限り分離した状態でデータをリアルタイムで利用できるようにしようとしているため、Ably チャネルを使用してクライアントと通信し、可用性が変化するたびに Webhook をトリガーします。

    また、いかなる種類のステートフル接続も使用しないでください。

    データ

    現在、次の 2 つの主要なデータ タイプを保存する必要があります。

    • シェルターの情報。Redis ハッシュの形式をとり、次のプロパティを持つことができます。

      • キーの名前は country-city-number です。 (例:RO-CJ-01 )
      • 可用性 (例:300) )
      • 機能 (例:["disabled persons special acces", "counseling"]) )
      • リソース:
        {
         resource: quantity,
         or
         resource: list
         ...
        }
        例:
        {
         "water": "200 liters",
         "medicine": ["insuline", ...]
        }
      • 電気:yes/no
      • 加熱:yes/no
      • 位置:[longitude, latitude] または
        {
         longitude: number,
         latitude: number
        }
      • _id:これはランダムに生成されます
    • 場所の情報

      私たちにはできるのですが ネストされたクエリを実行して、指定された場所で利用可能な避難所を検索する場合は、クエリを簡素化して最適化するために、それらを別のデータ構造として保存することをお勧めします。これを行うには、Redis セットを使用し、要素に <geographical-unit>-<name> という名前を付けます。 (例:country-RO または city-CJ )。こうすることで重複も防止できます

      例:

       city-CJ : ["RO-CJ-01", "RO-CJ-02", "RO-CJ-03"]

    しかし、依然として問題が 1 つ残っています。それは、避難所に行くという国民の意図と実際のことをどうやって区別できるのかということです。 避難所の管理者の確認によって占有率が更新されますか?これには 2 つの方法があります:

    <オル>
  • 常に更新する 避難所の空き状況キー:ユーザーが (一人で、または家族と一緒になど) 来る意向を表明 => x ずつ増加します。管理者は確認が無効であることに気づきました => x ずつ減少します (または -x ずつ増加します)

    ここでの問題は、管理者が真実の情報源として機能し、市民の位置を追跡しなければならないことです。また、避難所のデータはすぐには信頼できません

  • 別の文字列キーを作成する shelter-"availability" という名前 (例:RO-CJ-01-availability ) し、リアルタイムで更新された値を保存します。これにより、リアルタイムで更新し、ハッシュの可用性キーを信頼できる情報源として維持できます。

    クライアント側では、ハッシュと文字列キーの両方を取得し、実際の可用性と予測された可用性としてそれらを提示することに注意してください。別のアプローチとしては、文字列のみをフェッチし、必要に応じて真実のソースに戻るという方法もあります。これによりネットワーク負荷は軽減されますが、管理者は (最初のシナリオのように) データを常に検証し、実際に 取得する量が少ない場合は、シェルターの可用性キーを個別に保存する必要があります (他の情報を取得する必要があることを忘れないでください!)。

  • 並べ替え

    ソートセットと呼ばれる別の Redis データ型を利用してみましょう。ある場所のバンカーを可用性、設備、または利用可能なリソースに基づいて並べ替えたいとします。前に述べたように、ネストされたクエリを実行できますが、時間とデータ負荷が大幅に増加します。より良い解決策は、すべてのフィルタリング基準に対してソートされたセットを作成することです (それらに <geographical-unit>-<name>-<criteria> という名前を付けることができます) 、city-CJ-availability など または country-RO-food )

    例:city-B-availability

    スコア コンテンツ 200RO-B-02100RO-B-01

    この例では、可用性スコアは total seats - current occupation として計算されました。 .

    API とクライアントの動作をデモンストレーションするための基本的なコードをいくつか書くことができます

    エンドポイント

    主に、次のものが必要です。

    • クライアントに要求された情報を提供するデータ エンドポイントと
    • データ型を作成または更新するための edpoint

    クライアント

    ユーザーの位置を追跡した後、自動的に「空き状況」チャネルに接続し、住民が地下壕に行くつもりであればメッセージを公開します。

    まず、/_app.js から接続してみましょう。 ファイル:

    import { useEffect, useState } from "react";
     
    import "../styles/globals.css";
     
    import { configureAbly } from "@ably-labs/react-hooks";
     
    export default function App({ Component, pageProps }) {
     const [loaded, setLoaded] = useState(false);
     useEffect(() => {
     configureAbly({
     // In a production system, you should use authentication
     key: process.env.NEXT_PUBLIC_ABLY_API_KEY,
     });
     setLoaded(true);
     }, []);
     
     if (!loaded) return <div>loading...</div>;
     return <Component {...pageProps} />;
    }

    次に、必要なコンポーネントのチャネルに接続します。

    import { useChannel } from "@ably-labs/react-hooks";
     
    export default function Test() {
     const [availability] = useChannel("availability", (msg) => {
     console.log(msg);
     });
     
     return <></>;
    }

    データベースの操作

    新しいデータの追加

    新しいデータを Redis に追加するには、HSET、SET、SADD コマンドを使用できます。

    export default async (req) => {
     let data = await req.json();
     
     if (data.type === "shelter") {
     // Remove the 'type' key as it is not neccesary anymore
     delete data.type;
     const { name: shelter, availability } = data;
     
     let shelterData = data;
     // Generate a random id.
     shelterData._id = Math.random()
     .toString(36)
     .replace(/[^a-z]+/g, "")
     .substring(0, 7);
     
     // Store the shelter's info as a hash
     await redis.hset(shelter, shelterData);
     
     // Store the realtime-updated availability as a string
     await redis.set(shelter + "-availability", availability);
     return new Response("ok");
     } else if (data.type === "location") {
     const { name: location, shelters } = data;
     
     await redis.sadd(location, ...shelters);
     
     return new Response("ok");
     }
    };

    既存のデータを更新する

    基本的な UD (更新と削除) 操作以外に、Redis INCRBY および HINCRBY コマンドを使用してシェルターの可用性を変更できます。

    市民が地下壕に行く意向を表明した場合、クライアント アプリからメッセージを公開できます。

    availability.publish("update", {
     shelter: "RO-CJ-01",
     availability: 1, // Or -x, if the user cancels.
    });

    アーキテクチャで説明したように、これにより Webhook がトリガーされ、そこからデータを取得して shelter-"availability" を更新できます。 キー。

    await redis.incrby(shelter + "-availability", value);

    サーバーから更新している場合 (例:管理者の確認)、代わりに REST API を使用することを忘れないでください。

    データを取得しています

    サーバー上では、 GET 、 SMEMBERS 、および HGETALL コマンドを使用できます。

    クライアントでは、チャネル内のメッセージをリッスンし、それに応じて状態を更新できます。

    まとめると

    今日は、強力なサーバーレス アーキテクチャを活用して現実世界の緊急追跡アプリを構築する方法を検討しました。これを実現するには複数のアプローチがありますが、開発者エクスペリエンスが簡素化されるため、個人的にはこの種のフローを採用することをお勧めします。

    あなたは分散コンピューティング システムの構築に慣れている上級開発者で、マネージド サービスの必要性を感じているかもしれません。あるいは、あなたは初心者だが、世界を良い方向に変える可能性のあるアイデアを持っているかもしれません。適切なツールを見つけることは常にプロセスの重要な部分です。

    この記事についてのご意見をお聞かせください。質問がある場合は、LinkedIn で私にメッセージを送信するか、Github で私の他のコードをチェックしてください。


    1. AWSLambdaとサーバーレスRedisに裏打ちされたReactネイティブアプリの構築

      この投稿では、React Native、サーバーレスフレームワーク、およびUpstashを使用して、リーダーボードを表示および更新するためのモバイルアプリケーションを開発します。 React Nativeを使用して、AWSLambdaで実行されるPython関数で構成されるサーバーレスフレームワークに基づくモバイルアプリケーションを開発します。 1-UpstashRedisの使用 一般的なリーダーボードアプリでは、ユーザー情報とユーザーに属するスコアを保存する必要があります。これらのデータはすべてスコアで並べ替える必要があるため、Redisを使用することが最善の解決策の1つです。 R

    2. Vercel Edge と Upstash Redis を使用して Next.js にレート制限を実装する

      この記事では、Vercel Edge Middleware と @upstash/ratelimit ライブラリを利用して Web アプリケーションにレート制限を実装するプロセスについて説明します。後者は、レート制限データの保存と管理のためにバックエンドで Redis を利用します。 Vercel Edge を使用する利点 Vercel Edge は、ユーザーに最も近い場所で計算を実行するコンピューティング プラットフォームです。リクエストがバックエンドに到達する前にインターセプトする Vercel Edge Middleware を利用します。私は、いくつかの理由から、これがレート制限の実