Token导航 LogoToken导航

Agent Skill · 研究检索

caching-strategies(缓存策略)

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

caching-strategies 是研究检索类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为操作浏览器;许可证信息还不明确,第三方扫描已通过,按安装量在研究检索类的 73,675 个 Skill 里排第 51,124。

总安装 593周安装 24GitHub Stars 777下载 186核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 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

这个 Skill 是做什么的

研究检索类 Skill 主要解决「找资料、核对事实、把来源整理清楚」的问题,通常会让助手先检索再总结。

caching-strategies 用于加速慢查询与高频访问数据,适合在 Codex、Claude、Cursor、Gemini CLI 中需要优化外部 API 响应或会话数据时使用。它覆盖 HTTP 层、应用层与数据库层缓存,支持 TTL、失效策略与穿透保护,提升整体响应速度。

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

来源仓库内路径:skills/caching-strategies

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/dadbodgeoff/drift --skill caching-strategies;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要操作浏览器,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

caching-strategies 怎么安装?

在终端执行 npx skills add https://github.com/dadbodgeoff/drift --skill caching-strategies。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

caching-strategies 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

caching-strategies 需要什么权限?

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

caching-strategies 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

caching-strategies 用的人多吗?

公开数据是累计安装 593 次,近一周安装 24 次,下载 186 次,GitHub 777 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

caching-strategies 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理研究检索类任务、又不想每次都手写提示词的人。

不太适合

  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 SLA 的生产系统。

研究检索类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
find-skills

寻找技能 · Codex、Claude

31,199,81316,486操作浏览器MIT有提醒
self-improving-agent

自我改进 Agent · OpenClaw

16,464,0023,396接触敏感数据MIT-0通过
soultrace

灵魂追踪 · Codex、Claude

7,588,94412需要联网未明确有提醒
self-improving

自我完善 · OpenClaw

6,829,2841,046需要联网MIT-0通过
microsoft-foundry

微软代工厂 · Codex、Claude

6,614,144764调用外部服务未明确有提醒
caching-strategies

缓存策略 · 本页

593777操作浏览器未明确通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

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

平台分布

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