Cache Redis avec Claude Code
Découvrez cache Redis avec Claude Code. Conseils pratiques et exemples de code inclus.
Redis キャッシュの重要性
Redisはインメモリデータストアとして、キャッシュ、セッション管理、リアルタイム処理に広く使われています。Claude Codeを使えば、適切なキャッシュ戦略を設計し効率的に実装できます。
基本的なキャッシュ層
import { Redis } from "ioredis";
const redis = new Redis(process.env.REDIS_URL!);
class CacheService {
private redis: Redis;
private defaultTTL: number;
constructor(redis: Redis, defaultTTL = 300) {
this.redis = redis;
this.defaultTTL = defaultTTL;
}
async get<T>(key: string): Promise<T | null> {
const data = await this.redis.get(key);
if (!data) return null;
try {
return JSON.parse(data) as T;
} catch {
return null;
}
}
async set<T>(key: string, value: T, ttl?: number): Promise<void> {
const serialized = JSON.stringify(value);
await this.redis.set(key, serialized, "EX", ttl ?? this.defaultTTL);
}
async delete(key: string): Promise<void> {
await this.redis.del(key);
}
async deletePattern(pattern: string): Promise<void> {
const keys = await this.redis.keys(pattern);
if (keys.length > 0) {
await this.redis.del(...keys);
}
}
}
const cache = new CacheService(redis);
Cache-Aside パターン
async function getPostById(id: string): Promise<Post | null> {
const cacheKey = `post:${id}`;
// 1. キャッシュから取得
const cached = await cache.get<Post>(cacheKey);
if (cached) {
return cached;
}
// 2. DBから取得
const post = await prisma.post.findUnique({
where: { id },
include: { author: true, categories: true },
});
if (!post) return null;
// 3. キャッシュに保存(5分)
await cache.set(cacheKey, post, 300);
return post;
}
// 更新時のキャッシュ無効化
async function updatePost(id: string, data: Partial<Post>) {
const updated = await prisma.post.update({
where: { id },
data,
});
// 関連するキャッシュを無効化
await cache.delete(`post:${id}`);
await cache.deletePattern("posts:list:*");
return updated;
}
リスト結果のキャッシュ
async function getPostsList(params: {
page: number;
category?: string;
}): Promise<PaginatedResult<Post>> {
const cacheKey = `posts:list:${params.page}:${params.category || "all"}`;
const cached = await cache.get<PaginatedResult<Post>>(cacheKey);
if (cached) return cached;
const result = await fetchPostsFromDB(params);
// リスト結果は短めのTTL(1分)
await cache.set(cacheKey, result, 60);
return result;
}
キャッシュデコレータ
function Cacheable(ttl: number = 300) {
return function (
target: any,
propertyKey: string,
descriptor: PropertyDescriptor
) {
const originalMethod = descriptor.value;
descriptor.value = async function (...args: any[]) {
const cacheKey = `${target.constructor.name}:${propertyKey}:${JSON.stringify(args)}`;
const cached = await cache.get(cacheKey);
if (cached) return cached;
const result = await originalMethod.apply(this, args);
await cache.set(cacheKey, result, ttl);
return result;
};
return descriptor;
};
}
class PostService {
@Cacheable(300)
async getById(id: string) {
return prisma.post.findUnique({ where: { id } });
}
@Cacheable(60)
async getPopular(limit: number = 10) {
return prisma.post.findMany({
where: { published: true },
orderBy: { viewCount: "desc" },
take: limit,
});
}
}
セッション管理
import session from "express-session";
import RedisStore from "connect-redis";
const redisStore = new RedisStore({
client: redis,
prefix: "sess:",
ttl: 86400, // 24時間
});
app.use(
session({
store: redisStore,
secret: process.env.SESSION_SECRET!,
resave: false,
saveUninitialized: false,
cookie: {
secure: process.env.NODE_ENV === "production",
httpOnly: true,
maxAge: 86400 * 1000,
sameSite: "strict",
},
})
);
レート制限
async function rateLimiter(
key: string,
maxRequests: number,
windowSeconds: number
): Promise<{ allowed: boolean; remaining: number; resetAt: number }> {
const now = Math.floor(Date.now() / 1000);
const windowKey = `ratelimit:${key}:${Math.floor(now / windowSeconds)}`;
const current = await redis.incr(windowKey);
if (current === 1) {
await redis.expire(windowKey, windowSeconds);
}
const remaining = Math.max(0, maxRequests - current);
const resetAt = (Math.floor(now / windowSeconds) + 1) * windowSeconds;
return {
allowed: current <= maxRequests,
remaining,
resetAt,
};
}
// ミドルウェアとして使用
async function rateLimitMiddleware(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
const key = req.ip || "unknown";
const result = await rateLimiter(key, 100, 60);
res.set("X-RateLimit-Remaining", String(result.remaining));
res.set("X-RateLimit-Reset", String(result.resetAt));
if (!result.allowed) {
return res.status(429).json({ error: "Too many requests" });
}
next();
}
Claude Codeでの活用
Redisキャッシュの実装をClaude Codeに依頼する例です。エッジでのキャッシュについてはエッジコンピューティング、非同期処理はジョブキュー・非同期処理も参照してください。
Redisキャッシュ層を設計して。
- Cache-Asideパターンでの読み取りキャッシュ
- 更新時のキャッシュ無効化戦略
- APIレート制限
- セッション管理
- キャッシュのヒット率モニタリング
Redisの詳細はRedis公式ドキュメントを参照してください。Claude Codeの使い方は公式ドキュメントで確認できます。
Summary
Redisキャッシュはアプリケーションのパフォーマンスを劇的に向上させます。Claude Codeを使えば、キャッシュ戦略の設計から無効化パターンの実装まで、一貫したキャッシュ層を構築できます。
Related Posts
Maîtriser les Hooks de Claude Code : Formatage automatique, tests automatiques et plus encore
Apprenez à configurer le formatage et les tests automatiques avec les hooks de Claude Code. Inclut des exemples de configuration pratiques et des cas d'utilisation concrets.
Configuration des serveurs MCP dans Claude Code et cas d'utilisation pratiques
Un guide complet sur les capacités des serveurs MCP de Claude Code. Apprenez à connecter des outils externes, configurer des serveurs et découvrez des exemples d'intégration concrets.
Le guide complet pour rédiger un CLAUDE.md : Bonnes pratiques de configuration de projet
Un guide approfondi pour rédiger des fichiers CLAUDE.md efficaces. Apprenez à communiquer votre stack technologique, vos conventions et la structure de votre projet pour maximiser la qualité des réponses de Claude Code.