Express.jsでRedisキャッシュを構築する方法:ステップバイステップガイド
本記事では、Redisキャッシュを活用したサンプルアプリケーションを、解説付きでご紹介します。
Express Node.jsアプリケーションの基本的な作成方法については別記事で詳しく解説しているので、そちらを参考にすれば、スムーズに本題に入ることができます。
なぜキャッシュが必要なのか?
同じレスポンスを何度も返す必要がある場合、あらかじめデータを分散サーバーのメモリ上に保存しておくことで、リクエストのたびにストレージ層からデータを取得するよりも、はるかに高速に応答できます。キャッシュとは、アプリケーションが一定期間データの複製を保持し、Webリクエストに即座に応答できるようにする仕組みです。
以下のようなケースでは、キャッシュが特に効果を発揮します。
- サードパーティAPIを呼び出す必要があり、呼び出し回数に上限やコストが伴う場合
- クラウドとサーバー間のデータ転送コストが課題になる場合
- 同時リクエストの増加に応じたサーバーレスポンス速度が重要になる場合
Redisキャッシュとは?
Redisは、中央集権型の分散システム上にデータキャッシュを保存する仕組みです。「データ構造サーバー」とも呼ばれ、複数のプロセスが同時にデータを照会・更新しても、大きなロード時間が発生しないのが特徴です。
Redisの主な利点
Redisのデータ構造には、次のような特長があります。
- データが頻繁に要求・提供・更新される場合でも、RAMではなくディスクにデータを永続化できます。
- 高水準プログラミング言語と異なり、メモリを最適に使うことに重点を置いた実装になっています。
- レプリケーション、耐久性レベルの選択、クラスタリング、高可用性(HA)などの機能を備えています。
- リスト、セット、ソート済みセットなど、Memcachedでは扱いにくい複雑なデータ操作にも対応できます。
ローカル環境へのRedisクライアントのインストール
Redisを利用するには、まずローカルシステムにNode.js用のRedisクライアントをインストールします。Windows OSの場合は、GitHubからmsiファイル(本記事執筆時点の安定版はv3.0.504)をダウンロードし、通常の手順でインストールを進めてください。
最新のRedisクライアントは、Windows Subsystem for Linux(WSL)経由でインストールし、Redis 6.x系を利用することもできます。また、Dockerで環境を構築する場合や、Mac・Linux OSを使用する場合は、公式ダウンロードページの手順に従ってください。
以下のコマンドでRedisサーバーを起動します。
redis-server

Express Node.jsアプリケーションの作成
PowerShellまたはコマンドプロンプトを開き、作業用フォルダに移動します。
次のコマンドを実行して、プロジェクトのひな形を作成します。
npx express expressRedisCaching --hbs

続いて、以下のコマンドで必要なモジュールをインストールします。
npm i
さらに、今回のデモに必要な追加パッケージをインストールします。
npm i redis
npm i isomorphic-fetch
すべてのパッケージのインストールが完了したら、実装の準備は整いました。ここでは「getCached.js」という新しいルートファイルを作成し、「App.js」でマッピングしています。
app.use('/getCached', require('./routes/getCached'));
このエンドポイントが呼び出されると、まずJSON Placeholder(モックAPI)からレスポンスを取得し、そのデータをRedisキャッシュに保存したうえでリクエストに応答します。2回目以降のリクエストでは、キャッシュされたデータが即座に返されます。
const express = require('express')
require('isomorphic-fetch')
const redis = require('redis')
const router = express.Router()
// Redisクライアントの生成
const client = redis.createClient({
host: '127.0.0.1',
port: 6379
})
let sourceURL = 'https://jsonplaceholder.typicode.com/todos';
router.get('/', async (req, res) => {
await client.connect();
// キャッシュの有無を確認
const value = await client.get('todos');
if (value) {
console.log('from cached data')
res.send(JSON.parse(value))
} else {
// キャッシュがなければ元のAPIから取得
const resp = await fetch(sourceURL)
.then((response) => response.json());
// 取得したデータをキャッシュに保存
await client.set('todos', JSON.stringify(resp));
console.log('from source data')
res.send(resp);
}
await client.disconnect();
})
module.exports = router
redisモジュールでクライアントオブジェクトを生成する部分は、次のようになっています。
redis.createClient({ host: '127.0.0.1', port: 6379 });
各オプションの意味は以下の通りです。
host:今回はRedisがローカル環境で稼働しているため、デフォルトの127.0.0.1を指定しています。
port:Windows OSではデフォルトで6379番ポートがRedisに割り当てられますが、任意のポートに変更することも可能です。
それでは、次のコマンドでアプリケーションを起動しましょう。
npm start


初回アクセス時は、ソースAPIからデータを取得するため、レスポンスタイムは約1156ミリ秒かかりました。この結果はメモリ内データストアであるRedisキャッシュに保存されます。2回目のアクセスではキャッシュからデータが返され、取得時間はわずか約10ミリ秒、測定によっては約6ミリ秒まで短縮されました。
このように、ほんの数ステップの簡単な実装だけで、キャッシュによる大幅な高速化を実現できます。
-
【Redis入門】LPOP・BLPOPコマンドでリストの先頭要素を削除して取得する方法
このチュートリアルでは、Redisデータストア内のキーに保存されたリスト値の先頭(最初)の要素を削除して取得する方法を解説します。そのために、RedisのLPOPコマンドとBLPOPコマンドを使用します。 LPOPコマンドとは LPOPコマンドは、指定されたキーに格納されているリスト値の先頭要素を削除し、その要素を返します。キーが存在しない場合はnilが返され、キーは存在するものの格納されている値がリスト型でない場合にはエラーが返されます。Redis LPOPコマンドの構文は以下のとおりです。 構文 redis host:post> LPOP <keyname> 戻り値 -
-
Ably・Upstash Redis・Node.jsで構築するリアルタイムチャットアプリの作り方
本記事では、ユーザーがチャットグループに参加し、リアルタイムでコミュニケーションできるシンプルなリアルタイムチャットアプリケーションを作成します。 低レイテンシでユーザー間のリアルタイムメッセージングを実現する「Ably」、メッセージを永続的に保存する「Upstash Redis」、そしてアプリケーションを構築するための「Node.js」という3つの技術を組み合わせて実装していきます。 Ablyとは Ablyは、ユーザー間の双方向通信を可能にするリアルタイムエクスペリエンスプラットフォームです。 このチャットアプリでは、AblyのPub/Subチャネルを活用します。ユーザーはAblyチャネルに