UpstashでAPIのレスポンスをCacheしてみる【Redis】
こんばんは。みなさん、Upstashをご存知でしょうか?
知らない方のために、まずUpstashの説明をさせていただきます。
1.Upstashとは?
とあるように、Upstashは、サーバーレスなデータベースを提供するサービスであり、主にRedisを活用しています。
さらに、Kafkaも利用することができます。
嬉しいことに、東京リージョンも利用でき、REST APIを通じて操作することができます。
Redis自体は、既に経験がある方も多いかもしれません。
今回は、Upstashが提供するサーバーレスなRedisを使用して、APIのレスポンスをキャッシュする実験を行ってみたいと思います。
2.なぜRedisでCacheするのか?
今回ECの新規開発にて、以下のような要件と課題がありました。
この要件と課題を解決するための解決策として、Redisを使用してコンテンツのAPIレスポンスをキャッシュする方法を選択しました。
では早速やっていきます。
Upstashの登録など諸々の説明は省略しますが、Upstashを登録してDBを東京リージョンで作成します。
作成が完了すればREST APIやNodeなど、様々な方法で接続が可能になります。
今回はNext.jsを使用しているので、Node.jsから接続したいと思います。
3.ioredisをインストールする
まずは、redisに接続するためのライブラリであるioredisをインストールします。
$ yarn add -D ioredis
4.Redisの接続情報をenvに設定する
次に、UpstashからRedisに接続するための接続情報を取得し、それを環境変数(env)に設定します。
// .env
REDIS_PASSWORD="" // Upstashから取得
REDIS_PORT="" // Upstashから取得
REDIS_HOST="" // Upstashから取得
X_ENDPOINT_PRODUCTS="" // MicroCMSからデータをFetchするのでついでに追加
X_ENDPOINT_PRODUCTS="" // MicroCMSからデータをFetchするのでついでに追加
5.ioredisを初期化する
ioredisを使いやすくするために、初期化した関数をexportします。以下のように実装できます。
// redis.ts
export const redisClient = new Redis(`rediss://:${process.env.REDIS_PASSWORD ?? ''}@${process.env.REDIS_HOST ?? ''}:${process.env.REDIS_PORT ?? ''}`, {
tls: { rejectUnauthorized: false }
});
初期化が完了したので、早速レスポンスをキャッシュに保存する処理を行います。
以下に、それぞれのステップを説明します。
// fetch.ts
import { redisClient } from './redis';
//-----------------------------------------------------------------
// 商品の詳細情報を取得する
//-----------------------------------------------------------------
getProductDetail = async (productId: number) => {
try {
// RedisにCacheがあるかどうかをチェックする
const productDetail = await redisClient.get(`product_detail_${productId}`);
// Cacheが無ければMicroCMSからデータを取得してRedisに保存してからreturnする
if (!productDetail) {
const datas = await this.microCMSClient.fetchGetDetail({
endpoint: process.env.X_ENDPOINT_PRODUCTS ?? '',
contentId: handle
});
await redisClient.set(`product_detail_${productId}`, JSON.stringify(datas), 'EX', 60 * 60 * 24 * 6);
return datas;
}
// CacheがあればJSONをparseしてreturnする
return JSON.parse(productDetail) as IProductDetail;
} catch (e) {
return {
error: {
message: e instanceof Error ? e.message : {}
}
};
}
};
このような処理を行うことで、Redisにキャッシュが存在すればMicroCMSからデータを取得せずに直接データを返すことが可能になります。
Redisはデータの取得が高速であるため、TTFB(First Byte Time)を低減することができますね。
6.Cache更新のタイミング
Cacheが存在しない場合はMicroCMSからデータを取得しますが、商品詳細情報が更新された場合にはどうすれば良いでしょうか?
Cacheに保存された情報が古くなってしまっている状況ですね。
MicroCMSでは、情報が更新された際にWebhookのPOSTを起動することができます。
このWebhookが発火した時に、RedisのキャッシュをクリアするAPIを呼び出すことで、商品情報の更新タイミングでRedisのキャッシュをクリアし、最新の情報を取得する動作を実現できます。
Next.jsのISRなどは、強整合性の必要がないサイトでは有用な場合もありますが、ECサイトなどの強整合性が必要なサイトでは、コンテンツをキャッシュさせるためにこの方法は有効です。
それでは。