自動パイプライン処理により v0.dev のロード時間を 50% 短縮
Vercel KV は Web プロジェクトにとって非常に貴重なツールですが、広範囲に使用すると HTTP リクエストの数が急速に増加し、パフォーマンスに影響を与える可能性があります。 Redis パイプラインはコマンドをバッチ処理してリクエストを削減する方法を提供しますが、実装が難しい場合があります。パイプラインの効率性と基本的な Redis コマンドのシンプルさを組み合わせるソリューションはありますか? 自動パイプラインが登場します。 – 複雑なコーディングを行わずにパフォーマンスを向上させるシームレスな方法を提供します。
問題
Redis がデータ ソースとして広く使用されている Web ページを構築したと想像してください。複数のコンポーネントが独自の Redis 呼び出しを行い、一部のコンポーネントはさまざまなコンテンツで複数回レンダリングされます。
この設定では、Web ページが開かれるたびに、Redis への大量のリクエストが生成される可能性があります。膨大な量のリクエストによりかなりのオーバーヘッドが生じ、パフォーマンスに影響を与えます。さらに、同時 HTTP リクエストの数が厳しく制限されている Cloudflare Workers のような環境では、これは重大な問題になります。
通常のパイプライン
このような状況における従来の解決策は、Redis パイプラインを使用することです。パイプラインを使用すると、リクエストを 1 つずつ送信する代わりに、複数のコマンドを収集して一緒に実行できます。このようにして、単一の HTTP リクエストで複数の Redis コマンドが実行されるため、HTTP リクエストの数が大幅に削減され、パフォーマンスが向上します。
import { kv } from '@vercel/kv';
const pipeline = kv.pipeline();
pipeline.set("foo", "bar");
pipeline.get("foo");
const res = await pipeline.exec();
console.log(res); // ["OK", "bar"] パイプラインの短所
ただし、パイプラインを使用すると、プログラマの観点からは大幅なオーバーヘッドが発生します。パイプライン API は標準の Redis API とは異なるため、パイプライン API の有効化または無効化は簡単な作業ではありません。
さらに、単一のパイプライン内のさまざまなコンポーネントのデータをリクエストする必要がある場合は、データが使用される場所とは別にフェッチ ロジックを作成する必要があります。この分離により、コードベースが断片化され、保守性が低下する可能性があります。
自動パイプライン
自動パイプラインはこれらの問題にシームレスに対処します。自動パイプラインを使用すると、既存のコードを変更せずにプロジェクトでパイプライン機能を有効にすることができます。 Redis クライアントは可能な限り自動的にコマンドをバッチ処理し、パフォーマンスを簡単に向上させながら、通常どおり Redis を使用し続けることができます。
自動パイプラインが一般的なシナリオ、つまり複数のキーの値をフェッチする方法を最適化する方法を見てみましょう。
const keys = ["key1", "key2", "key3"];
const values = await Promise.all(keys.map(key => kv.get(key))); パイプラインを使用しない場合、このコードは 3 つの HTTP リクエストを Redis に送信します。ただし、自動パイプラインを有効にすると、これらのリクエストは 1 つの HTTP リクエストにまとめられます。
慣用的な React サーバー コンポーネントの自動パイプライン
React Server Components (RSC) は独自のデータをフェッチできます。一般的な例は、次のように実装されるツイート コンポーネントです。
async function Tweet({id}) {
const tweet = kv.get(`tweets:${id}`)
return <div>{tweet.text}</div>
} このコンポーネントを
のようなループで呼び出すと、{tweetIds.map(id => <Tweet id={id} />)} 上の例と同じ N 個のバックエンド リクエストをトリガーします。もう一度、自動パイプラインを有効にすると、慣用的な反応コードを保持しながら、N 個のコマンドが 1 つのパイプラインにバッチ化されます。
仕組み
自動パイプラインは、バックグラウンドで「アクティブなパイプライン」を維持することによって機能します。コマンドはそれ自体をパイプラインに追加し、deferExecution を呼び出します。 :
private async deferExecution() {
await Promise.resolve()
return await Promise.resolve()
}
deferExecution を呼び出すと 、このコマンドは Node.js メインスレッドの制御を譲ります。次の GET その後、シーケンス内のコマンドがスレッドの制御を取得し、最初の GET とまったく同じことを実行して実行を続行します。 :自身をアクティブなパイプラインに追加し、スレッドの制御を譲ります。
以下に、自動パイプライン ロジックを疑似コードとして示します。
let activePipeline: Pipeline;
let pipelinePromises: new WeakMap<Pipeline, Promise<Array<unknown>>>();
let commandIndex: number;
const executeCommand = (command) => {
activePipeline = activePipeline || createNewPipeline();
activePipeline.addCommand(command);
commandIndex++;
const pipelinePromise = deferExecution().then(() => {
if (!pipelinePromises.has(activePipeline) {
const pipelinePromise = pipeline.exec();
pipelinePromises.set(pipeline, pipelinePromise);
activePipeline = null;
commandIndex = 0
};
return pipelinePromises.get(activePipeline)!;
});
const result = await pipelinePromise;
return result[commandIndex];
};
自分自身をアクティブなパイプラインに追加した後、3 番目の GET deferExecution も呼び出します 。この時点では、他に譲るコマンドがないため、遅延された GET の 1 つが実行されます。 コマンドは制御を取り戻し、パイプラインを実行します。
この例では、このパイプラインは 3 つの結果を返し、それぞれが最初のコマンドに対応します。各コマンドは引数のインデックスを追跡し、バッチ応答から正しい結果を確実に受け取ります。
自動パイプライン ロジックの背後にあるコードは、ここから入手できます。
v0.dev の自動パイプライン
v0.dev のパフォーマンスに対する自動パイプラインの影響は、ランディング ページの改善から明らかです。ランディング ページでは、過去のクエリと世代の例が紹介されています。まず、表示する項目のリストをフェッチし、次に項目ごとに個別にフェッチを行うため、多数の Redis リクエストが発生します。

自動パイプラインを有効にすると、スイッチを入れるだけでこのプロセスが最適化されます。現在、2 番目の部分は複数の個別のフェッチを必要としていたが、単一のパイプライン オペレーションに統合されています。
自動パイプラインが実装される前は、これらの Redis リクエストによって大量の個別の HTTP リクエストが発生し、ページの読み込み時間が遅くなっていました。ただし、自動パイプラインを有効にすると、これらのリクエストは効率的にパイプラインにバッチ処理され、必要な HTTP リクエストの数が減ります。その結果、ページの読み込み時間が改善され、約 450 ミリ秒から約 200 ミリ秒に短縮されました。
v0 チームは当初、自分たち自身のためのハックとして自動パイプラインを出荷しました。自動パイプラインは、Upstash の Redis クライアント v1.31.3 および Vercel KV v2.0 で利用できるようになりました。
-
Upstash Kafka、Redis、Next.js を使用してリアルタイム チャット アプリを構築する
プロジェクトの説明 このブログ投稿では、ユーザーがメッセージ クライアントとチャット ルームを作成できるメッセージング アプリケーションを作成します。さらに、ユーザーは過去のメッセージにアクセスできるようになります。 プロジェクトは 2 ページで構成されます。最初のページはクライアント登録専用であり、一意の名前を持つ複数のクライアントを作成できます。 クライアントのユーザー名をクリックすると、その特定のユーザーに関連付けられたチャットルーム クライアントに移動します。 チャット アプリケーションのロジックは次のとおりです。 ユーザーはインデックス ページ上に複数のクライアント
-
Flutter、サーバーレスフレームワーク、Upstash(REDIS)を備えたフルスタックサーバーレスアプリ-パート1
この投稿では、データを保存するためのFlutter、Serverless Framework、Upstash、Redisを使用してサーバーレスモバイルアプリケーションを構築します。 Upstashとは? Upstashは、Redis用のサーバーレスデータベースです。 Upstashを使用すると、リクエストごとに支払います。これは、データベースが使用されていないときに課金されないことを意味します。 Upstashはデータベースを構成および管理します。これは、DynamoDBやFaunaなどの他のデータベースの強力な代替手段であり、などの利点があります。 低レイテンシ REDISAPIと同