Node.js と Redis 分散キャッシュを使用して高性能 URL 短縮ツールを構築する
このチュートリアルでは、Node.js と Redis を使用してスケーラブルな URL 短縮サービスを構築します。このサービスは分散キャッシュを活用して、高トラフィックを効率的に処理し、遅延を削減し、シームレスに拡張します。システムの高速性と信頼性を確保するために、一貫性のあるハッシュ、キャッシュ無効化戦略、シャーディングなどの主要な概念について説明します。
このガイドを完了すると、分散キャッシュを使用してパフォーマンスを最適化する、完全に機能する URL 短縮サービスが完成します。また、ユーザーが URL を入力して、キャッシュのヒットやミスなどのリアルタイムの指標を確認できるインタラクティブなデモも作成します。
何を学ぶか
-
Node.js を使用して URL 短縮サービスを構築する方法 とレディス .
-
分散キャッシュを実装する方法 パフォーマンスを最適化します。
-
一貫したハッシュについて理解する およびキャッシュ無効化戦略 .
-
Docker の使用 シャーディングとスケーリングのために複数の Redis インスタンスをシミュレートします。
前提条件
開始する前に、以下がインストールされていることを確認してください。
-
Node.js (v14 以降)
-
レディス
-
ドッカー
-
JavaScript、Node.js、Redis の基本的な知識。
目次
-
プロジェクトの概要
-
ステップ 1:プロジェクトのセットアップ
-
ステップ 2:Redis インスタンスのセットアップ
-
ステップ 3:URL 短縮サービスの実装
-
ステップ 4:キャッシュ無効化の実装
-
ステップ 5:キャッシュ メトリックの監視
-
ステップ 6:アプリケーションのテスト
-
結論:学んだこと
プロジェクトの概要
以下の URL 短縮サービスを構築します。
<オル>ユーザーは長い URL を短縮して、元の URL を取得できます。
このサービスはRedis キャッシュを使用します。 短縮 URL と元の URL の間のマッピングを保存します。
キャッシュは、高トラフィックを処理するために複数の Redis インスタンスに分散されます。
システムはキャッシュ ヒットを示します。 そしてミスします。 リアルタイムで。
システム アーキテクチャ
スケーラビリティとパフォーマンスを確保するために、サービスを次のコンポーネントに分割します。
<オル>API サーバー :URL の短縮および取得のリクエストを処理します。
Redis キャッシュ レイヤー :分散キャッシュに複数の Redis インスタンスを使用します。
ドッカー :複数の Redis コンテナを含む分散環境をシミュレートします。
ステップ 1:プロジェクトのセットアップ
Node.js アプリケーションを初期化して、プロジェクトをセットアップしましょう。
mkdir scalable-url-shortener
cd scalable-url-shortener
npm init -y
次に、必要な依存関係をインストールします。
npm install express redis shortid dotenv
-
express:軽量の Web サーバー フレームワーク。 -
redis:キャッシュを処理します。 -
shortid:短い一意の ID を生成します。 -
dotenv:環境変数の管理用。
.env を作成します。 プロジェクトのルートにあるファイル:
PORT=3000
REDIS_HOST_1=localhost
REDIS_PORT_1=6379
REDIS_HOST_2=localhost
REDIS_PORT_2=6380
REDIS_HOST_3=localhost
REDIS_PORT_3=6381
これらの変数は、使用する Redis ホストとポートを定義します。
ステップ 2:Redis インスタンスのセットアップ
Docker を使用して、複数の Redis インスタンスがある分散環境をシミュレートします。
次のコマンドを実行して、3 つの Redis コンテナを起動します。
docker run -p 6379:6379 --name redis1 -d redis
docker run -p 6380:6379 --name redis2 -d redis
docker run -p 6381:6379 --name redis3 -d redis
これにより、異なるポートで実行される 3 つの Redis インスタンスがセットアップされます。これらのインスタンスを使用して一貫性のあるハッシュを実装します。
ステップ 3:URL 短縮サービスの実装
メインのアプリケーション ファイル index.js を作成しましょう。 :
require('dotenv').config();
const express = require('express');
const redis = require('redis');
const shortid = require('shortid');
const app = express();
app.use(express.json());
const redisClients = [
redis.createClient({ host: process.env.REDIS_HOST_1, port: process.env.REDIS_PORT_1 }),
redis.createClient({ host: process.env.REDIS_HOST_2, port: process.env.REDIS_PORT_2 }),
redis.createClient({ host: process.env.REDIS_HOST_3, port: process.env.REDIS_PORT_3 })
];
// Hash function to distribute keys among Redis clients
function getRedisClient(key) {
const hash = key.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0);
return redisClients[hash % redisClients.length];
}
// Endpoint to shorten a URL
app.post('/shorten', async (req, res) => {
const { url } = req.body;
if (!url) return res.status(400).send('URL is required');
const shortId = shortid.generate();
const redisClient = getRedisClient(shortId);
await redisClient.set(shortId, url);
res.json({ shortUrl: `http://localhost:${process.env.PORT}/${shortId}` });
});
// Endpoint to retrieve the original URL
app.get('/:shortId', async (req, res) => {
const { shortId } = req.params;
const redisClient = getRedisClient(shortId);
redisClient.get(shortId, (err, url) => {
if (err || !url) {
return res.status(404).send('URL not found');
}
res.redirect(url);
});
});
app.listen(process.env.PORT, () => {
console.log(`Server running on port ${process.env.PORT}`);
});
このコードからわかるように、次のものがあります:
<オル>一貫したハッシュ :
-
単純なハッシュ関数を使用して、キー (短縮 URL) を複数の Redis クライアントに配布します。
-
ハッシュ関数により、URL が Redis インスタンス全体に均等に分散されます。
URL の短縮 :
-
/ 短縮 エンドポイントは長い URL を受け入れ、shortid を使用して短い ID を生成します。 ライブラリ。
-
短縮 URL は、ハッシュ関数を使用して Redis インスタンスの 1 つに保存されます。
URL リダイレクト :
-
/:shortId エンドポイントはキャッシュから元の URL を取得し、ユーザーをリダイレクトします。
-
URL がキャッシュ内に見つからない場合、404 応答が返されます。
ステップ 4:キャッシュ無効化の実装
実際のアプリケーションでは、URL は期限切れになったり、時間の経過とともに変更される場合があります。これに対処するにはキャッシュの無効化を実装する必要があります。 .
キャッシュされた URL に有効期限を追加する
index.js を変更しましょう。 ファイルを使用して、キャッシュされた各エントリの有効期限を設定します。
// Endpoint to shorten a URL with expiration
app.post('/shorten', async (req, res) => {
const { url, ttl } = req.body; // ttl (time-to-live) is optional
if (!url) return res.status(400).send('URL is required');
const shortId = shortid.generate();
const redisClient = getRedisClient(shortId);
await redisClient.set(shortId, url, 'EX', ttl || 3600); // Default TTL of 1 hour
res.json({ shortUrl: `http://localhost:${process.env.PORT}/${shortId}` });
});
-
TTL (生存時間) :デフォルトの有効期限は1 時間に設定されています。 短縮URLごとに。必要に応じて、URL ごとに TTL をカスタマイズできます。
-
キャッシュの無効化 :TTL の有効期限が切れると、エントリはキャッシュから自動的に削除されます。
ステップ 5:キャッシュ メトリックの監視
キャッシュ ヒットを監視するには そしてミスします。 index.js でエンドポイントにログを追加します。 :
app.get('/:shortId', async (req, res) => {
const { shortId } = req.params;
const redisClient = getRedisClient(shortId);
redisClient.get(shortId, (err, url) => {
if (err || !url) {
console.log(`Cache miss for key: ${shortId}`);
return res.status(404).send('URL not found');
}
console.log(`Cache hit for key: ${shortId}`);
res.redirect(url);
});
});
このコードで何が起こっているかは次のとおりです。
-
キャッシュ ヒット :URL がキャッシュ内で見つかった場合、それはキャッシュ ヒットです。
-
キャッシュミス :URL が見つからない場合は、キャッシュ ミスです。
-
このログは、分散キャッシュのパフォーマンスを監視するのに役立ちます。
ステップ 6:アプリケーションのテスト
<オル>docker start redis1 redis2 redis3
<オル> node index.js
<オル>
エンドポイントをテストする curl を使用 または郵便配達員:
-
URL を短縮します:
POST http://localhost:3000/shorten Body: { "url": "https://example.com" } -
短縮 URL にアクセスします。
GET http://localhost:3000/{shortId}
結論:学んだこと
おめでとうございます!スケーラブルなURL 短縮サービスの構築に成功しました。 分散キャッシュを使用 Node.js と Redis を使用します。このチュートリアルを通じて、次の方法を学習しました。
<オル>一貫したハッシュを実装する キャッシュ エントリを複数の Redis インスタンスに分散します。
キャッシュ無効化戦略を使用してアプリケーションを最適化します。 データを最新の状態に保つため。
Docker を使用する 複数の Redis ノードを含む分散環境をシミュレートします。
キャッシュのヒットとミスを監視します。 パフォーマンスを最適化します。
次のステップ:
-
データベースを追加 :URL をデータベースに保存して、キャッシュを超えて永続化します。
-
分析を実装する :短縮 URL のクリック数と分析を追跡します。
-
クラウドへの導入 :自動スケーリングと復元力のために Kubernetes を使用してアプリケーションをデプロイします。
コーディングを楽しんでください!
無料でコーディングを学びましょう。 freeCodeCamp のオープンソース カリキュラムは、40,000 人以上の人々が開発者としての職に就くのに役立ちました。始めましょう
-
Redis LTRIM –Redisデータストアに保存されている既存のリストをトリミングする方法
このチュートリアルでは、redisデータストアのキーに保存されている既存のリスト値をトリミングする方法について学習します。このために、Redis LTRIMを使用します コマンド。 LTIMコマンド このコマンドは、結果のリスト値に指定された範囲の要素のみが含まれるように、既存のリスト値をトリミングします。範囲は、部分文字列の開始インデックスと終了インデックスを決定する開始(包括的)オフセットと終了(包括的)オフセットによって定義されます。 インデックスはゼロベースであるため、0は最初の要素を意味し、1は2番目の要素を意味します。負の数を使用して、文字列値の末尾からオフセットを指定する
-
Redis APPEND –Redisの既存の文字列値に文字列を追加する方法
このチュートリアルでは、redisデータストアのキーに保存されている既存の文字列値に文字列を追加する方法について学習します。このために、Redis APPENDを使用します コマンド。 APPENDコマンド このコマンドは、指定された文字列を、キーに格納されている既存の文字列値に追加します。キーがredisデータストアに存在しない場合は、追加操作を実行する前に、最初にキーが作成され、空の文字列に設定されます。キーは存在するが、キーに格納されている値が文字列でない場合、エラーが返されます。 Redis APPENDコマンドの構文は次のとおりです:- 構文:- redis host:po