关于 redis-best-practices
redis-best-practices 是面向 Redis 应用开发与运维的实践指南,涵盖数据结构、缓存、可靠性、安全和性能,并提供命令示例。
主要功能
- 01Redis 数据结构选择建议
- 02键命名与过期策略
- 03缓存与失效模式
- 04事务与原子操作
- 05高可用、持久化与安全
- 06监控与性能实践
适用场景
- 01为队列或排行榜选择数据结构
- 02设计缓存 TTL 与失效策略
- 03规划 Redis 复制与持久化
- 04检查 Redis 内存和连接设置
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ mindrally/ skills --skill redis-best-practices安装后在 Claude Code 中输入/redis-best-practices确认已加载。
详细介绍
Redis 最佳实践
核心原则
- 使用 Redis 进行缓存、会话存储、实时分析和消息队列
- 根据使用场景选择合适的数据结构
- 制定恰当的键命名规范和过期策略
- 根据高可用性和持久化需求进行设计
- 监控内存使用情况并优化性能
键命名规范
- 使用冒号分隔命名空间
- 在键名中包含对象类型和标识符
- 键名应简短且具有描述性
- 在整个应用中使用一致的命名模式
# Good key naming examples
user:1234:profile
user:1234:sessions
order:5678:items
cache:api:products:list
queue:email:pending
session:abc123def456
rate_limit:api:user:1234
数据结构
字符串
- 用于简单的键值存储、计数器和缓存
- 可考虑使用 MGET/MSET 进行批量操作
# Simple caching
SET cache:user:1234 '{"name":"John","email":"[email protected]"}' EX 3600
# Counters
INCR stats:pageviews:homepage
INCRBY stats:downloads:file123 5
# Atomic operations
SETNX lock:resource:456 "owner:abc" EX 30
哈希
- 用于包含多个字段的对象
- 比使用多个字符串键更节省内存
- 支持部分更新
# Store user profile
HSET user:1234 name "John Doe" email "[email protected]" created_at "2024-01-15"
# Get specific fields
HGET user:1234 email
HMGET user:1234 name email
# Increment numeric fields
HINCRBY user:1234 login_count 1
# Get all fields
HGETALL user:1234
列表
- 用于队列、最近项目和活动动态
- 可考虑为队列消费者使用阻塞操作
# Message queue
LPUSH queue:emails '{"to":"[email protected]","subject":"Welcome"}'
RPOP queue:emails
# Blocking pop for workers
BRPOP queue:emails 30
# Recent activity (keep last 100)
LPUSH user:1234:activity "viewed product 567"
LTRIM user:1234:activity 0 99
# Get recent items
LRANGE user:1234:activity 0 9
集合
- 用于唯一值集合、标签和关系
- 支持集合运算(并集、交集、差集)
# User tags/interests
SADD user:1234:interests "technology" "music" "travel"
# Check membership
SISMEMBER user:1234:interests "music"
# Find common interests
SINTER user:1234:interests user:5678:interests
# Online users tracking
SADD online:users "user:1234"
SREM online:users "user:1234"
SMEMBERS online:users
有序集合
- 用于排行榜、优先级队列和时间序列数据
- 元素按分数排序
# Leaderboard
ZADD leaderboard:game1 1500 "player:123" 2000 "player:456" 1800 "player:789"
# Get top 10
ZREVRANGE leaderboard:game1 0 9 WITHSCORES
# Get player rank
ZREVRANK leaderboard:game1 "player:123"
# Time-based data (score = timestamp)
ZADD events:user:1234 1705329600 "login" 1705330000 "purchase"
# Get events in time range
ZRANGEBYSCORE events:user:1234 1705329600 1705333200
流
- 用于事件流和日志数据
- 支持消费者组,以便进行分布式处理
# Add events to stream
XADD events:orders * customer_id 1234 product_id 567 amount 99.99
# Read from stream
XREAD COUNT 10 STREAMS events:orders 0
# Consumer groups
XGROUP CREATE events:orders order-processors $ MKSTREAM
XREADGROUP GROUP order-processors worker1 COUNT 10 STREAMS events:orders >
# Acknowledge processed messages
XACK events:orders order-processors 1234567890-0
缓存模式
Cache-Aside 模式
# Pseudo-code for cache-aside
def get_user(user_id):
# Try cache first
cached = redis.get(f"cache:user:{user_id}")
if cached:
return json.loads(cached)
# Cache miss - fetch from database
user = database.get_user(user_id)
# Store in cache with expiration
redis.setex(f"cache:user:{user_id}", 3600, json.dumps(user))
return user
Write-Through 模式
def update_user(user_id, data):
# Update database
database.update_user(user_id, data)
# Update cache
redis.setex(f"cache:user:{user_id}", 3600, json.dumps(data))
缓存失效
# Delete specific cache
DEL cache:user:1234
# Delete by pattern (use with caution in production)
# Use SCAN instead of KEYS for large datasets
SCAN 0 MATCH cache:user:* COUNT 100
# Tag-based invalidation using sets
SADD cache:tags:user:1234 "cache:user:1234:profile" "cache:user:1234:orders"
# Invalidate all related caches
SMEMBERS cache:tags:user:1234
# Then delete each key
过期与内存管理
TTL 最佳实践
- 始终为缓存键设置 TTL
- 使用随机抖动,避免惊群效应
- 会话数据可考虑使用滑动过期
# Set with expiration
SET cache:data:123 "value" EX 3600
# Set expiration on existing key
EXPIRE cache:data:123 3600
# Check TTL
TTL cache:data:123
# Persist key (remove expiration)
PERSIST cache:data:123
内存管理
# Check memory usage
INFO memory
# Get key memory usage
MEMORY USAGE cache:large:object
# Configure max memory policy
CONFIG SET maxmemory 2gb
CONFIG SET maxmemory-policy allkeys-lru
事务与原子性
MULTI/EXEC 事务
# Transaction block
MULTI
INCR stats:views
LPUSH recent:views "page:123"
EXEC
# Watch for optimistic locking
WATCH user:1234:balance
balance = GET user:1234:balance
MULTI
SET user:1234:balance (balance - 100)
EXEC
Lua 脚本
- 用于复杂的原子操作
- 脚本以原子方式执行
-- Rate limiting script
local key = KEYS[1]
local limit = tonumber(ARGV[1])
local window = tonumber(ARGV[2])
local current = tonumber(redis.call('GET', key) or '0')
if current >= limit then
return 0
end
redis.call('INCR', key)
if current == 0 then
redis.call('EXPIRE', key, window)
end
return 1
# Execute Lua script
EVAL "return redis.call('GET', KEYS[1])" 1 mykey
发布/订阅与消息传递
# Publisher
PUBLISH channel:notifications '{"type":"alert","message":"New order"}'
# Subscriber
SUBSCRIBE channel:notifications
# Pattern subscription
PSUBSCRIBE channel:*
高可用性
复制
- 使用副本扩展读取能力
- 在主节点上配置恰当的持久化
# On replica
REPLICAOF master_host 6379
# Check replication status
INFO replication
Redis Sentinel
- 用于自动故障转移
- 至少部署 3 个 Sentinel 实例
Redis Cluster
- 用于水平扩展
- 数据会自动分片到各节点
- 为相关键使用哈希标签
# Hash tags ensure keys go to same slot
SET {user:1234}:profile "data"
SET {user:1234}:settings "data"
持久化
RDB 快照
# Manual snapshot
BGSAVE
# Configure automatic snapshots
CONFIG SET save "900 1 300 10 60 10000"
AOF(仅追加文件)
# Enable AOF
CONFIG SET appendonly yes
CONFIG SET appendfsync everysec
# Rewrite AOF
BGREWRITEAOF
安全
- 要求进行身份验证
- 使用 TLS 连接
- 绑定到指定接口
- 禁用危险命令
# Set password
CONFIG SET requirepass "your_strong_password"
# Authenticate
AUTH your_strong_password
# Rename dangerous commands (in redis.conf)
rename-command FLUSHALL ""
rename-command FLUSHDB ""
rename-command KEYS ""
监控
# Server info
INFO
# Memory stats
INFO memory
# Client connections
CLIENT LIST
# Slow log
SLOWLOG GET 10
# Monitor commands (debug only)
MONITOR
# Key count per database
INFO keyspace
连接管理
- 使用连接池
- 设置恰当的超时时间
- 妥善处理重新连接
# Python example with connection pool
import redis
pool = redis.ConnectionPool(
host='localhost',
port=6379,
max_connections=50,
socket_timeout=5,
socket_connect_timeout=5
)
redis_client = redis.Redis(connection_pool=pool)
性能提示
- 使用流水线进行批量操作
- 避免使用大型键(值超过 100 KB)
- 在生产环境中使用 SCAN,而不是 KEYS
- 监控并优化内存使用情况
- 复杂的 JSON 操作可考虑使用 RedisJSON
# Pipeline example (pseudo-code)
pipe = redis.pipeline()
pipe.get("key1")
pipe.get("key2")
pipe.set("key3", "value")
results = pipe.execute()
评论
支持 Markdown