mcpField
C
caching-strategist

caching-strategist

github.com/patricio0312rev开发63266 次安装41 周前更新
代码仓库

关于 caching-strategist

面向软件开发者的缓存策略设计技能,涵盖多层缓存、键与 TTL 规划、失效和预热,并提供正确性检查清单。

主要功能

  1. 01规划 CDN、应用、数据库和客户端缓存
  2. 02设计分层缓存键与 TTL
  3. 03实现 cache-aside 与失效流程
  4. 04预热缓存并防止缓存击穿
  5. 05检查回退、监控和缓存正确性

适用场景

  1. 01为不同变化频率的数据选择 TTL
  2. 02设计更新时的缓存失效规则
  3. 03减少热门查询的重复加载
  4. 04检查缓存故障时的回退与监控

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/patricio0312rev/skills --skill caching-strategist

安装后在 Claude Code 中输入/caching-strategist确认已加载。

详细介绍

缓存策略设计师

设计高效的缓存策略,兼顾性能与一致性。

缓存层

CDN:静态资源、公开页面(TTL:天/周) 应用缓存(Redis):API 响应、会话(TTL:分钟/小时) 数据库缓存:查询结果(TTL:秒/分钟) 客户端缓存:浏览器/应用本地缓存

缓存键策略

// Hierarchical key structure
const CACHE_KEYS = {
  user: (id: string) => `user:${id}`,
  userPosts: (userId: string, page: number) => `user:${userId}:posts:${page}`,
  post: (id: string) => `post:${id}`,
  postComments: (postId: string) => `post:${postId}:comments`,
};

// Include version in keys for easy invalidation
const CACHE_VERSION = "v1";
const key = `${CACHE_VERSION}:${CACHE_KEYS.user(userId)}`;

TTL 策略

const TTL = {
  // Frequently changing
  REALTIME: 10, // 10 seconds
  SHORT: 60, // 1 minute

  // Moderate updates
  MEDIUM: 300, // 5 minutes
  STANDARD: 3600, // 1 hour

  // Rarely changing
  LONG: 86400, // 1 day
  VERY_LONG: 604800, // 1 week
};

// Usage
await redis.setex(key, TTL.MEDIUM, JSON.stringify(data));

Cache-Aside 模式

export const getCachedUser = async (userId: string): Promise<User> => {
  const key = CACHE_KEYS.user(userId);

  // Try cache first
  const cached = await redis.get(key);
  if (cached) {
    return JSON.parse(cached);
  }

  // Cache miss - fetch from DB
  const user = await db.users.findById(userId);

  // Store in cache
  await redis.setex(key, TTL.STANDARD, JSON.stringify(user));

  return user;
};

缓存失效

// Invalidate on update
export const updateUser = async (userId: string, data: UpdateUserDto) => {
  const user = await db.users.update(userId, data);

  // Invalidate cache
  await redis.del(CACHE_KEYS.user(userId));

  // Invalidate related caches
  await redis.del(CACHE_KEYS.userPosts(userId, "*"));

  return user;
};

// Tag-based invalidation
const addCacheTags = (key: string, tags: string[]) => {
  tags.forEach((tag) => {
    redis.sadd(`cache_tag:${tag}`, key);
  });
};

const invalidateByTag = async (tag: string) => {
  const keys = await redis.smembers(`cache_tag:${tag}`);
  if (keys.length) {
    await redis.del(...keys);
    await redis.del(`cache_tag:${tag}`);
  }
};

缓存预热

// Pre-populate cache for common queries
export const warmCache = async () => {
  const popularPosts = await db.posts.findPopular(100);

  for (const post of popularPosts) {
    const key = CACHE_KEYS.post(post.id);
    await redis.setex(key, TTL.LONG, JSON.stringify(post));
  }
};

// Schedule warming
cron.schedule("0 */6 * * *", warmCache); // Every 6 hours

缓存击穿防护

// Use locks to prevent multiple simultaneous fetches
export const getCachedWithLock = async (
  key: string,
  fetchFn: () => Promise<any>
) => {
  const cached = await redis.get(key);
  if (cached) return JSON.parse(cached);

  const lockKey = `lock:${key}`;
  const acquired = await redis.set(lockKey, "1", "EX", 10, "NX");

  if (acquired) {
    try {
      // Fetch and cache
      const data = await fetchFn();
      await redis.setex(key, TTL.STANDARD, JSON.stringify(data));
      return data;
    } finally {
      await redis.del(lockKey);
    }
  } else {
    // Wait for other request to finish
    await new Promise((resolve) => setTimeout(resolve, 100));
    return getCachedWithLock(key, fetchFn);
  }
};

缓存正确性检查清单

- [ ] Cache keys are unique and predictable
- [ ] TTL is appropriate for data freshness
- [ ] Invalidation happens on all updates
- [ ] Related caches invalidated together
- [ ] Cache stampede prevention in place
- [ ] Fallback to DB if cache fails
- [ ] Monitoring cache hit rate
- [ ] Cache size doesn't grow unbounded
- [ ] Sensitive data not cached or encrypted
- [ ] Cache warming for critical paths

最佳实践

  • 积极缓存不可变数据
  • 对频繁变化的数据设置较短的 TTL
  • 在写入时而非读取时使缓存失效
  • 监控命中率并进行调整
  • 使用标签批量使缓存失效
  • 防止缓存击穿
  • 缓存不可用时优雅降级

输出检查清单

  • 缓存键命名策略
  • 各类数据的 TTL 值
  • 已记录缓存失效触发条件
  • Cache-Aside 实现
  • 缓存击穿防护
  • 缓存预热策略
  • 监控/指标配置
  • 已完成正确性检查清单

评论

支持 Markdown