Token导航 LogoToken导航TokenDH.com
研究检索操作浏览器github未标认证来源可访问许可证需确认审计通过

caching-strategies缓存策略

Agent Skill

caching-strategies 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

593

周安装

24

GitHub Stars

777

下载量

186
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:caching-strategies(缓存策略)
来源仓库:https://github.com/dadbodgeoff/drift
仓库路径:skills/caching-strategies
安装命令:
npx skills add https://github.com/dadbodgeoff/drift --skill caching-strategies
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/dadbodgeoff/drift --skill caching-strategies

简介

caching-strategies 用于加速慢查询与高频访问数据,适合在 Codex、Claude、Cursor、Gemini CLI 中需要优化外部 API 响应或会话数据时使用。

  • 它覆盖 HTTP 层、应用层与数据库层缓存,支持 TTL、失效策略与穿透保护,提升整体响应速度。
  • 使用时需根据数据变更频率选择合适策略,避免缓存一致性问题;建议结合监控评估命中率。
  • 安装前请确认权限范围,注意是否会触发内存或持久化存储操作,确保缓存生命周期可控。
  • 适用宿主包括 Codex、Claude、Cursor、Gemini CLI,接入前应确认版本、权限和运行环境要求。

SKILL.md

Caching Strategies

Speed up your app with smart caching at every layer.

When to Use This Skill

  • Slow database queries
  • Expensive computations
  • External API responses
  • Session data
  • Frequently accessed data

Cache Layers

┌─────────────────────────────────────────────────────┐
│                    Request                           │
└─────────────────────────────────────────────────────┘
         │
         ▼
┌─────────────────────────────────────────────────────┐
│  Layer 1: HTTP Cache (CDN/Browser)                  │
│  - Static assets, public API responses              │
│  - Cache-Control headers                            │
└─────────────────────────────────────────────────────┘
         │ miss
         ▼
┌─────────────────────────────────────────────────────┐
│  Layer 2: In-Memory Cache (Node/Process)            │
│  - Hot data, computed values                        │
│  - LRU eviction                                     │
└─────────────────────────────────────────────────────┘
         │ miss
         ▼
┌─────────────────────────────────────────────────────┐
│  Layer 3: Distributed Cache (Redis)                 │
│  - Shared across instances                          │
│  - Session data, rate limits                        │
└─────────────────────────────────────────────────────┘
         │ miss
         ▼
┌─────────────────────────────────────────────────────┐
│  Layer 4: Database                                  │
└─────────────────────────────────────────────────────┘

TypeScript Implementation

Multi-Layer Cache

// cache.ts
import { Redis } from 'ioredis';
import { LRUCache } from 'lru-cache';

interface CacheOptions {
  ttl?: number;           // Time to live in seconds
  staleWhileRevalidate?: number;
  tags?: string[];        // For invalidation
}

class MultiLayerCache {
  private memory: LRUCache<string, { value: unknown; expires: number }>;
  private redis: Redis;

  constructor(redis: Redis) {
    this.redis = redis;
    this.memory = new LRUCache({
      max: 1000,
      ttl: 60 * 1000, // 1 minute default
    });
  }

  async get<T>(key: string): Promise<T | null> {
    // Layer 1: Memory
    const memoryHit = this.memory.get(key);
    if (memoryHit && memoryHit.expires > Date.now()) {
      return memoryHit.value as T;
    }

    // Layer 2: Redis
    const redisValue = await this.redis.get(key);
    if (redisValue) {
      const parsed = JSON.parse(redisValue) as T;
      // Populate memory cache
      this.memory.set(key, { value: parsed, expires: Date.now() + 60000 });
      return parsed;
    }

    return null;
  }

  async set<T>(key: string, value: T, options: CacheOptions = {}): Promise<void> {
    const ttl = options.ttl || 3600; // 1 hour default

    // Set in Redis
    await this.redis.setex(key, ttl, JSON.stringify(value));

    // Set in memory (shorter TTL)
    this.memory.set(key, {
      value,
      expires: Date.now() + Math.min(ttl * 1000, 60000),
    });

    // Track tags for invalidation
    if (options.tags) {
      for (const tag of options.tags) {
        await this.redis.sadd(`cache:tag:${tag}`, key);
      }
    }
  }

  async getOrSet<T>(
    key: string,
    fetcher: () => Promise<T>,
    options: CacheOptions = {}
  ): Promise<T> {
    const cached = await this.get<T>(key);
    if (cached !== null) {
      return cached;
    }

    // Prevent cache stampede with lock
    const lockKey = `lock:${key}`;
    const acquired = await this.redis.set(lockKey, '1', 'EX', 10, 'NX');

    if (!acquired) {
      // Another process is fetching, wait and retry
      await new Promise(resolve => setTimeout(resolve, 100));
      return this.getOrSet(key, fetcher, options);
    }

    try {
      const value = await fetcher();
      await this.set(key, value, options);
      return value;
    } finally {
      await this.redis.del(lockKey);
    }
  }

  async invalidate(key: string): Promise<void> {
    this.memory.delete(key);
    await this.redis.del(key);
  }

  async invalidateByTag(tag: string): Promise<void> {
    const keys = await this.redis.smembers(`cache:tag:${tag}`);
    if (keys.length > 0) {
      await this.redis.del(...keys);
      for (const key of keys) {
        this.memory.delete(key);
      }
    }
    await this.redis.del(`cache:tag:${tag}`);
  }
}

export { MultiLayerCache, CacheOptions };

Cache-Aside Pattern

// user-service.ts
class UserService {
  constructor(private cache: MultiLayerCache) {}

  async getUser(id: string): Promise<User> {
    return this.cache.getOrSet(
      `user:${id}`,
      async () => {
        return db.users.findUnique({ where: { id } });
      },
      { ttl: 3600, tags: ['users', `user:${id}`] }
    );
  }

  async updateUser(id: string, data: Partial<User>): Promise<User> {
    const user = await db.users.update({
      where: { id },
      data,
    });

    // Invalidate cache
    await this.cache.invalidate(`user:${id}`);

    return user;
  }

  async deleteUser(id: string): Promise<void> {
    await db.users.delete({ where: { id } });
    await this.cache.invalidateByTag(`user:${id}`);
  }
}

HTTP Caching Middleware

// http-cache-middleware.ts
import { Request, Response, NextFunction } from 'express';

interface HttpCacheOptions {
  maxAge?: number;
  sMaxAge?: number;
  staleWhileRevalidate?: number;
  private?: boolean;
  vary?: string[];
}

function httpCache(options: HttpCacheOptions = {}) {
  return (req: Request, res: Response, next: NextFunction) => {
    const directives: string[] = [];

    if (options.private) {
      directives.push('private');
    } else {
      directives.push('public');
    }

    if (options.maxAge !== undefined) {
      directives.push(`max-age=${options.maxAge}`);
    }

    if (options.sMaxAge !== undefined) {
      directives.push(`s-maxage=${options.sMaxAge}`);
    }

    if (options.staleWhileRevalidate !== undefined) {
      directives.push(`stale-while-revalidate=${options.staleWhileRevalidate}`);
    }

    res.setHeader('Cache-Control', directives.join(', '));

    if (options.vary) {
      res.setHeader('Vary', options.vary.join(', '));
    }

    next();
  };
}

// Usage
app.get('/api/products',
  httpCache({ maxAge: 60, sMaxAge: 300, staleWhileRevalidate: 86400 }),
  async (req, res) => {
    const products = await getProducts();
    res.json(products);
  }
);

Python Implementation

# cache.py
import json
import time
from typing import TypeVar, Callable, Optional
from functools import lru_cache
import redis

T = TypeVar('T')

class MultiLayerCache:
    def __init__(self, redis_client: redis.Redis):
        self.redis = redis_client
        self._memory: dict[str, tuple[any, float]] = {}

    def get(self, key: str) -> Optional[any]:
        # Layer 1: Memory
        if key in self._memory:
            value, expires = self._memory[key]
            if expires > time.time():
                return value
            del self._memory[key]

        # Layer 2: Redis
        redis_value = self.redis.get(key)
        if redis_value:
            parsed = json.loads(redis_value)
            self._memory[key] = (parsed, time.time() + 60)
            return parsed

        return None

    def set(self, key: str, value: any, ttl: int = 3600, tags: list[str] = None):
        self.redis.setex(key, ttl, json.dumps(value))
        self._memory[key] = (value, time.time() + min(ttl, 60))

        if tags:
            for tag in tags:
                self.redis.sadd(f"cache:tag:{tag}", key)

    async def get_or_set(
        self,
        key: str,
        fetcher: Callable[[], T],
        ttl: int = 3600,
    ) -> T:
        cached = self.get(key)
        if cached is not None:
            return cached

        # Simple lock for stampede prevention
        lock_key = f"lock:{key}"
        if not self.redis.set(lock_key, "1", ex=10, nx=True):
            await asyncio.sleep(0.1)
            return await self.get_or_set(key, fetcher, ttl)

        try:
            value = await fetcher()
            self.set(key, value, ttl)
            return value
        finally:
            self.redis.delete(lock_key)

    def invalidate_by_tag(self, tag: str):
        keys = self.redis.smembers(f"cache:tag:{tag}")
        if keys:
            self.redis.delete(*keys)
            for key in keys:
                self._memory.pop(key.decode(), None)
        self.redis.delete(f"cache:tag:{tag}")

Decorator Pattern

# cache_decorator.py
from functools import wraps

def cached(key_template: str, ttl: int = 3600, tags: list[str] = None):
    def decorator(func):
        @wraps(func)
        async def wrapper(*args, **kwargs):
            # Build cache key from template
            key = key_template.format(*args, **kwargs)

            cached_value = cache.get(key)
            if cached_value is not None:
                return cached_value

            result = await func(*args, **kwargs)
            cache.set(key, result, ttl=ttl, tags=tags)
            return result
        return wrapper
    return decorator

# Usage
@cached("user:{user_id}", ttl=3600, tags=["users"])
async def get_user(user_id: str) -> User:
    return await db.users.find_unique(where={"id": user_id})

Cache Invalidation Strategies

1. Time-Based (TTL)

await cache.set('key', value, { ttl: 3600 }); // Expires in 1 hour

2. Event-Based

// On data change
eventBus.on('user.updated', async (userId) => {
  await cache.invalidate(`user:${userId}`);
});

3. Tag-Based

// Set with tags
await cache.set(`product:${id}`, product, { tags: ['products', `category:${categoryId}`] });

// Invalidate all products in category
await cache.invalidateByTag(`category:${categoryId}`);

4. Write-Through

async function updateUser(id: string, data: Partial<User>) {
  const user = await db.users.update({ where: { id }, data });
  await cache.set(`user:${id}`, user); // Update cache immediately
  return user;
}

Best Practices

  1. Cache at the right layer - Don't cache everything in Redis
  2. Use appropriate TTLs - Balance freshness vs performance
  3. Prevent stampedes - Use locks or stale-while-revalidate
  4. Monitor hit rates - Track cache effectiveness
  5. Plan for invalidation - Use tags for related data

Common Mistakes

  • Caching user-specific data without proper keys
  • No cache invalidation strategy
  • TTLs too long (stale data) or too short (no benefit)
  • Caching errors or null values
  • Not handling cache failures gracefully

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

35.99%
按下载量换算67

Claude

28.16%
按下载量换算52

Cursor

18.48%
按下载量换算34

Gemini CLI

9.47%
按下载量换算18

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

操作浏览器

该 Skill 可能涉及浏览器控制能力,使用时可能读取或操作网页内容,需要在受控环境中确认权限边界。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills