基于 SOC 职业分类
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/tools-only/X-Skills --skill caching命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
Index of Build Systems Skills
Coordination patterns for distributed dataflow systems including barriers, epochs, and distributed snapshots
Windowing, sessionization, time-series aggregation, and late data handling for streaming systems
| name | caching |
| description | Implement multi-tier database caching with Redis, in-memory, and CDN layers... |
| shortcut | cach |
Implement production-grade multi-tier caching architecture for databases using Redis (distributed cache), in-memory caching (L1), and CDN (static assets) to reduce database load by 80-95%, improve query latency from 50ms to 1-5ms, and support horizontal scaling with cache-aside, write-through, and read-through patterns.
Use /caching when you need to:
DON'T use this when:
This command implements multi-tier caching with intelligent invalidation because:
Alternative considered: Read-through caching
Alternative considered: Database query result caching (pg_stat_statements)
Before running this command:
Define hierarchical cache keys for easy invalidation (e.g., user:123:profile).
Check cache first, query database on miss, populate cache with result.
Set appropriate TTL based on data freshness requirements and memory limits.
Invalidate cache on data updates using event listeners or explicit invalidation.
Track hit rate, miss rate, latency, and memory usage with Prometheus/Grafana.
The command generates:
caching/redis_client.py - Redis connection pool and wrappercaching/cache_decorator.py - Python decorator for automatic cachingcaching/cache_invalidation.js - Event-driven invalidation logiccaching/cache_monitoring.yml - Prometheus metrics and alertscaching/cache_warming.sql - SQL queries for cache preloading#!/usr/bin/env python3
"""
Production-ready multi-tier caching system with L1 (in-memory) and
L2 (Redis) caches, automatic invalidation, and performance monitoring.
"""
import redis
import pickle
from typing import Optional, Callable, Any
from functools import wraps
from datetime import timedelta
import time
import logging
from cachetools import TTLCache
import hashlib
import json
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class MultiTierCache:
"""
Two-tier caching system with L1 (in-memory) and L2 (Redis).
L1: Fast in-memory cache (1-5ms) for hot data
L2: Distributed Redis cache (5-10ms) shared across servers
"""
def __init__(
self,
redis_url: str = "redis://localhost:6379/0",
l1_max_size: int = 1000,
l1_ttl_seconds: int = 60,
l2_ttl_seconds: int = 3600,
enabled: bool = True
):
"""
Initialize multi-tier cache.
Args:
redis_url: Redis connection URL
l1_max_size: Max entries in L1 cache
l1_ttl_seconds: L1 cache TTL (default: 1 minute)
l2_ttl_seconds: L2 cache TTL (default: 1 hour)
enabled: Enable/disable caching (useful for debugging)
"""
self.enabled = enabled
if not enabled:
logger.warning()
.l1_cache = TTLCache(maxsize=l1_max_size, ttl=l1_ttl_seconds)
.l1_ttl = l1_ttl_seconds
.redis_client = redis.from_url(
redis_url,
decode_responses=,
socket_connect_timeout=,
socket_timeout=,
retry_on_timeout=
)
.l2_ttl = l2_ttl_seconds
.metrics = {
: ,
: ,
: ,
: ,
: ,
:
}
() -> :
key_parts = [(arg) arg args]
key_parts.extend( k, v (kwargs.items()))
key_suffix = hashlib.md5(
.join(key_parts).encode()
).hexdigest()[:]
() -> []:
.enabled:
key .l1_cache:
.metrics[] +=
logger.debug()
.l1_cache[key]
.metrics[] +=
:
cached_data = .redis_client.get(key)
cached_data:
.metrics[] +=
logger.debug()
value = pickle.loads(cached_data)
.l1_cache[key] = value
value
.metrics[] +=
redis.RedisError e:
logger.error()
.metrics[] +=
() -> :
.enabled:
:
.l1_cache[key] = value
serialized = pickle.dumps(value)
ttl = l2_ttl .l2_ttl
.redis_client.setex(key, ttl, serialized)
logger.debug()
redis.RedisError e:
logger.error()
.metrics[] +=
() -> :
.enabled:
:
.l1_cache.pop(key, )
.redis_client.delete(key)
logger.info()
redis.RedisError e:
logger.error()
.metrics[] +=
() -> :
.enabled:
:
cursor =
deleted_count =
:
cursor, keys = .redis_client.scan(
cursor,
=pattern,
count=
)
keys:
deleted_count += .redis_client.delete(*keys)
cursor == :
.l1_cache.clear()
logger.info()
deleted_count
redis.RedisError e:
logger.error()
.metrics[] +=
() -> :
total_l1 = .metrics[] + .metrics[]
total_l2 = .metrics[] + .metrics[]
l1_hit_rate = (
.metrics[] / total_l1 *
total_l1 >
)
l2_hit_rate = (
.metrics[] / total_l2 *
total_l2 >
)
overall_hit_rate = (
(.metrics[] + .metrics[]) /
(total_l1 + total_l2) *
(total_l1 + total_l2) >
)
{
: .metrics[],
: .metrics[],
: (l1_hit_rate, ),
: .metrics[],
: .metrics[],
: (l2_hit_rate, ),
: (overall_hit_rate, ),
: .metrics[],
: .metrics[]
}
cache = MultiTierCache()
():
() -> :
():
cache_key = cache._generate_key(prefix, *args, **kwargs)
cached_result = cache.get(cache_key)
cached_result :
cached_result
cache.metrics[] +=
result = func(*args, **kwargs)
cache.(cache_key, result, l2_ttl=l2_ttl)
result
wrapper
decorator
():
psycopg2
conn = psycopg2.connect()
conn.cursor() cur:
cur.execute(, (user_id,))
cur.fetchone()
():
psycopg2
conn = psycopg2.connect()
conn.cursor() cur:
cur.execute(
,
(user_id, limit)
)
cur.fetchall()
():
cache.delete_pattern()
():
psycopg2
conn = psycopg2.connect()
conn.cursor() cur:
set_clause = .join( k updates.keys())
cur.execute(
,
(*updates.values(), user_id)
)
conn.commit()
invalidate_user_cache(user_id)
logger.info()
__name__ == :
()
start = time.time()
profile1 = get_user_profile()
db_time = (time.time() - start) *
()
start = time.time()
profile2 = get_user_profile()
cache_time = (time.time() - start) *
()
()
()
(json.dumps(cache.get_metrics(), indent=))
#!/usr/bin/env python3
"""
Cache warming strategy to preload hot data before traffic hits.
Reduces cold start latency and improves cache hit rate.
"""
import psycopg2
from concurrent.futures import ThreadPoolExecutor, as_completed
import time
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class CacheWarmer:
"""
Preload cache with frequently accessed data.
"""
def __init__(self, cache: MultiTierCache, db_conn_string: str):
"""
Initialize cache warmer.
Args:
cache: MultiTierCache instance
db_conn_string: Database connection string
"""
self.cache = cache
self.db_conn_string = db_conn_string
def warm_user_profiles(self, user_ids: list[int]) -> dict:
"""
Preload user profiles for given IDs.
Args:
user_ids: List of user IDs to warm
Returns:
Statistics (count, duration, errors)
"""
start_time = time.time()
stats = {'loaded': 0, 'errors': 0}
logger.info(f"Warming cache for {len(user_ids)} user profiles...")
with psycopg2.connect(self.db_conn_string) as conn:
with conn.cursor() as cur:
for user_id in user_ids:
:
cur.execute(
,
(user_id,)
)
profile = cur.fetchone()
profile:
cache_key =
.cache.(cache_key, profile, l2_ttl=)
stats[] +=
Exception e:
logger.error()
stats[] +=
duration = time.time() - start_time
stats[] = duration
logger.info(
)
stats
() -> :
start_time = time.time()
stats = {: , : }
logger.info()
psycopg2.connect(.db_conn_string) conn:
conn.cursor() cur:
cur.execute(, (limit,))
products = cur.fetchall()
product products:
:
product_id = product[]
cache_key =
.cache.(cache_key, product, l2_ttl=)
stats[] +=
Exception e:
logger.error()
stats[] +=
duration = time.time() - start_time
stats[] = duration
logger.info(
)
stats
() -> :
logger.info()
psycopg2.connect(.db_conn_string) conn:
conn.cursor() cur:
cur.execute()
hot_user_ids = [row[] row cur.fetchall()]
ThreadPoolExecutor(max_workers=) executor:
futures = {
executor.submit(.warm_user_profiles, hot_user_ids): ,
executor.submit(.warm_top_products, ):
}
results = {}
future as_completed(futures):
cache_type = futures[future]
:
results[cache_type] = future.result()
Exception e:
logger.error()
results
__name__ == :
multitiercache cache
warmer = CacheWarmer(
cache=cache,
db_conn_string=
)
results = warmer.warm_all_hot_data()
()
| Error | Cause | Solution |
|---|---|---|
| "Redis connection refused" | Redis server down or unreachable | Implement graceful degradation (bypass cache, query database directly) |
| "Out of memory" (Redis) | Cache size exceeds max memory | Configure eviction policy (maxmemory-policy allkeys-lru) or increase memory |
| "Pickle deserialization error" | Cached object structure changed | Version cache keys when data models change, invalidate old caches |
| "Cache stampede" | Many requests miss cache simultaneously | Use locking or probabilistic early expiration to prevent thundering herd |
| "Stale data returned" | TTL too long or invalidation missed | Reduce TTL, implement event-driven invalidation on updates |
Caching Patterns
Eviction Policies (Redis)
TTL Strategies
DO:
DON'T:
/database-connection-pooler - Optimize connections when cache is unavailable/database-health-monitor - Monitor cache hit rate and database load/sql-query-optimizer - Optimize queries that are cache misses/database-security-scanner - Audit sensitive data in cache