重要前提
安装AI Skills的关键前提是:必须科学上网,且开启TUN模式,这一点至关重要,直接决定安装能否顺利完成,在此郑重提醒三遍:科学上网,科学上网,科学上网。查看完整安装教程 →
npx skills add https://github.com/patricio0312rev/skills --skill caching-strategist设计有效的缓存策略以优化性能和一致性。
CDN : 静态资源、公开页面(TTL:天/周) 应用缓存 (Redis): API 响应、会话(TTL:分钟/小时) 数据库缓存 : 查询结果(TTL:秒/分钟) 客户端缓存 : 浏览器/应用本地缓存
// 分层键结构
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`,
};
// 在键中包含版本以便于失效
const CACHE_VERSION = "v1";
const key = `${CACHE_VERSION}:${CACHE_KEYS.user(userId)}`;
const TTL = {
// 频繁变更
REALTIME: 10, // 10 秒
SHORT: 60, // 1 分钟
// 适度更新
MEDIUM: 300, // 5 分钟
STANDARD: 3600, // 1 小时
// 很少变更
LONG: 86400, // 1 天
VERY_LONG: 604800, // 1 周
};
// 用法
await redis.setex(key, TTL.MEDIUM, JSON.stringify(data));
export const getCachedUser = async (userId: string): Promise<User> => {
const key = CACHE_KEYS.user(userId);
// 先尝试缓存
const cached = await redis.get(key);
if (cached) {
return JSON.parse(cached);
}
// 缓存未命中 - 从数据库获取
const user = await db.users.findById(userId);
// 存入缓存
await redis.setex(key, TTL.STANDARD, JSON.stringify(user));
return user;
};
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
// 更新时失效
export const updateUser = async (userId: string, data: UpdateUserDto) => {
const user = await db.users.update(userId, data);
// 使缓存失效
await redis.del(CACHE_KEYS.user(userId));
// 使相关缓存失效
await redis.del(CACHE_KEYS.userPosts(userId, "*"));
return user;
};
// 基于标签的失效
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}`);
}
};
// 为常见查询预填充缓存
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));
}
};
// 调度预热
cron.schedule("0 */6 * * *", warmCache); // 每 6 小时
// 使用锁防止多个同时获取
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 {
// 获取并缓存
const data = await fetchFn();
await redis.setex(key, TTL.STANDARD, JSON.stringify(data));
return data;
} finally {
await redis.del(lockKey);
}
} else {
// 等待其他请求完成
await new Promise((resolve) => setTimeout(resolve, 100));
return getCachedWithLock(key, fetchFn);
}
};
- [ ] 缓存键是唯一且可预测的
- [ ] TTL 适合数据新鲜度要求
- [ ] 所有更新操作都触发了失效
- [ ] 相关缓存一起失效
- [ ] 已实施缓存雪崩预防措施
- [ ] 缓存失败时回退到数据库
- [ ] 监控缓存命中率
- [ ] 缓存大小不会无限增长
- [ ] 敏感数据未缓存或已加密
- [ ] 关键路径已进行缓存预热
每周安装数
49
仓库
GitHub 星标数
21
首次出现
2026年1月24日
安全审计
安装于
codex41
opencode40
gemini-cli40
github-copilot39
cursor37
claude-code35
Design effective caching strategies for performance and consistency.
CDN : Static assets, public pages (TTL: days/weeks) Application Cache (Redis): API responses, sessions (TTL: minutes/hours) Database Cache : Query results (TTL: seconds/minutes) Client Cache : Browser/app local cache
// 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)}`;
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));
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
Weekly Installs
49
Repository
GitHub Stars
21
First Seen
Jan 24, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
codex41
opencode40
gemini-cli40
github-copilot39
cursor37
claude-code35
Azure 升级评估与自动化工具 - 轻松迁移 Functions 计划、托管层级和 SKU
127,000 周安装