Redis with Claude Code
Learn about redis using Claude Code. Practical tips and code examples included.
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();
}
Einsatz mit Claude Code
Redisキャッシュの実装をClaude Codeに依頼する例です。エッジでのキャッシュについてはエッジコンピューティング、非同期処理はジョブキュー・非同期処理も参照してください。
Redisキャッシュ層を設計して。
- Cache-Asideパターンでの読み取りキャッシュ
- 更新時のキャッシュ無効化戦略
- APIレート制限
- セッション管理
- キャッシュのヒット率モニタリング
Redisの詳細はRedis公式ドキュメントを参照してください。Claude Codeの使い方は公式ドキュメントで確認できます。
Zusammenfassung
Redisキャッシュはアプリケーションのパフォーマンスを劇的に向上させます。Claude Codeを使えば、キャッシュ戦略の設計から無効化パターンの実装まで、一貫したキャッシュ層を構築できます。
Related Posts
Claude Code Hooks meistern: Auto-Formatierung, Auto-Tests und mehr
Erfahren Sie, wie Sie Auto-Formatierung und Auto-Tests mit Claude Code Hooks einrichten. Inklusive praktischer Konfigurationsbeispiele und realer Anwendungsfälle.
Claude Code MCP-Server: Einrichtung und praktische Anwendungsfälle
Ein umfassender Leitfaden zu den MCP-Server-Funktionen von Claude Code. Erfahren Sie, wie Sie externe Tools anbinden, Server konfigurieren, und entdecken Sie praxisnahe Integrationsbeispiele.
Der komplette Leitfaden zum Schreiben von CLAUDE.md: Best Practices für die Projektkonfiguration
Ein umfassender Leitfaden zum Schreiben effektiver CLAUDE.md-Dateien. Erfahren Sie, wie Sie Ihren Tech-Stack, Konventionen und Projektstruktur kommunizieren, um die Ausgabequalität von Claude Code zu maximieren.