redis-best-practices
mindrally/skills
Redis 開發的最佳實務:快取、資料結構與高效能的鍵值操作
...展開全部關於redis-best-practices
「Redis 最佳實務」技能課程提供全面性的指導,協助開發者有效運用 Redis 作為記憶體內資料儲存庫。課程涵蓋快取、會話儲存、即時分析及訊息佇列的最佳實務模式,同時協助開發者避免常見的陷阱與效能問題。 本課程旨在解決如何充分發揮 Redis 潛力的挑戰,透過教授正確的資料結構選擇、金鑰命名規範,以及能確保可擴展性與可維護性的架構模式來達成此目標。
本技能著重於 Redis 的五種核心資料結構——字串、哈希、清單、集合和排序集合——以及用於事件處理的較新功能「串流」。針對每種結構,本技能皆提供實用的程式碼範例,示範何時以及如何使用原子操作、批次指令和阻塞操作。 主要主題包括實作高效的「緩存旁路(cache-aside)」模式、使用排序集設計排行榜、利用清單建構訊息佇列,以及透過消費者群組處理分散式事件處理。本課程的指導重點在於記憶體效率、適當的過期政策,以及一致的命名模式,這些都能讓 Redis 應用程式的除錯與擴展更加容易。
這項技能非常適合從事需快速資料存取的高效能應用程式開發的後端開發人員、設計快取層的 DevOps 工程師,以及建構即時系統的架構師。 無論您是實作會話管理、建置速率限制器、建立活動動態,還是設計分散式任務佇列,這項技能皆提供經過實戰驗證的模式與具體範例,可直接應用於生產環境系統。
常見問題
製作排行榜時應使用哪種資料結構?
請使用排序集(ZADD、ZREVRANGE),其中分數代表玩家排名。排序集會自動維持順序,並支援高效的排名查詢及基於分數的範圍運算。
如何實作適當的快取過期機制?
請透過 SET 指令搭配 EX 參數設定過期時間,或直接使用 SETEX 指令。根據資料變動頻率選擇 TTL 值——頻繁變動的資料應設定較短的 TTL(數秒至數分鐘),靜態內容則應設定較長的 TTL(數小時至數天)。
何時應使用哈希(hash)而非多個字串鍵?
儲存具有多個欄位的物件時,應使用雜湊。與為每個欄位分別建立字串金鑰相比,雜湊更能有效利用記憶體,並允許進行部分更新,無需擷取整個物件。
針對佇列,RPOP 與 BRPOP 之間有何差異?
RPOP 會立即返回一個值,若清單為空則返回 null。BRPOP 則是一項阻塞操作,會等待最長至指定超時時間,直到項目可用為止,因此非常適合需要高效等待新任務的工作程序。
如何使用 Redis Streams 處理分散式處理?
請使用 XGROUP CREATE 和 XREADGROUP 建立消費者群組。多個消費者可並行處理訊息,而 Redis 會追蹤每個消費者已接收的訊息。使用 XACK 來確認處理成功。
Redis Best Practices
Core Principles
- Use Redis for caching, session storage, real-time analytics, and message queuing
- Choose appropriate data structures for your use case
- Implement proper key naming conventions and expiration policies
- Design for high availability and persistence requirements
- Monitor memory usage and optimize for performance
Key Naming Conventions
- Use colons as namespace separators
- Include object type and identifier in key names
- Keep keys short but descriptive
- Use consistent naming patterns across your application
# Good key naming examplesuser:1234:profileuser:1234:sessionsorder:5678:itemscache:api:products:listqueue:email:pendingsession:abc123def456rate_limit:api:user:1234Data Structures
Strings
- Use for simple key-value storage, counters, and caching
- Consider using MGET/MSET for batch operations
# Simple cachingSET cache:user:1234 '{"name":"John","email":"[email protected]"}' EX 3600# CountersINCR stats:pageviews:homepageINCRBY stats:downloads:file123 5# Atomic operationsSETNX lock:resource:456 "owner:abc" EX 30Hashes
- Use for objects with multiple fields
- More memory-efficient than multiple string keys
- Supports partial updates
# Store user profileHSET user:1234 name "John Doe" email "[email protected]" created_at "2024-01-15"# Get specific fieldsHGET user:1234 emailHMGET user:1234 name email# Increment numeric fieldsHINCRBY user:1234 login_count 1# Get all fieldsHGETALL user:1234Lists
- Use for queues, recent items, and activity feeds
- Consider blocking operations for queue consumers
# Message queueLPUSH queue:emails '{"to":"[email protected]","subject":"Welcome"}'RPOP queue:emails# Blocking pop for workersBRPOP queue:emails 30# Recent activity (keep last 100)LPUSH user:1234:activity "viewed product 567"LTRIM user:1234:activity 0 99# Get recent itemsLRANGE user:1234:activity 0 9Sets
- Use for unique collections, tags, and relationships
- Supports set operations (union, intersection, difference)
# User tags/interestsSADD user:1234:interests "technology" "music" "travel"# Check membershipSISMEMBER user:1234:interests "music"# Find common interestsSINTER user:1234:interests user:5678:interests# Online users trackingSADD online:users "user:1234"SREM online:users "user:1234"SMEMBERS online:usersSorted Sets
- Use for leaderboards, priority queues, and time-series data
- Elements sorted by score
# LeaderboardZADD leaderboard:game1 1500 "player:123" 2000 "player:456" 1800 "player:789"# Get top 10ZREVRANGE leaderboard:game1 0 9 WITHSCORES# Get player rankZREVRANK leaderboard:game1 "player:123"# Time-based data (score = timestamp)ZADD events:user:1234 1705329600 "login" 1705330000 "purchase"# Get events in time rangeZRANGEBYSCORE events:user:1234 1705329600 1705333200Streams
- Use for event streaming and log data
- Supports consumer groups for distributed processing
# Add events to streamXADD events:orders * customer_id 1234 product_id 567 amount 99.99# Read from streamXREAD COUNT 10 STREAMS events:orders 0# Consumer groupsXGROUP CREATE events:orders order-processors $ MKSTREAMXREADGROUP GROUP order-processors worker1 COUNT 10 STREAMS events:orders ># Acknowledge processed messagesXACK events:orders order-processors 1234567890-0Caching Patterns
Cache-Aside Pattern
# Pseudo-code for cache-asidedef 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 Pattern
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))
Cache Invalidation
# Delete specific cacheDEL cache:user:1234# Delete by pattern (use with caution in production)# Use SCAN instead of KEYS for large datasetsSCAN 0 MATCH cache:user:* COUNT 100# Tag-based invalidation using setsSADD cache:tags:user:1234 "cache:user:1234:profile" "cache:user:1234:orders"# Invalidate all related cachesSMEMBERS cache:tags:user:1234# Then delete each keyExpiration and Memory Management
TTL Best Practices
- Always set TTL on cache keys
- Use jitter to prevent thundering herd
- Consider sliding expiration for session data
# Set with expirationSET cache:data:123 "value" EX 3600# Set expiration on existing keyEXPIRE cache:data:123 3600# Check TTLTTL cache:data:123# Persist key (remove expiration)PERSIST cache:data:123Memory Management
# Check memory usageINFO memory# Get key memory usageMEMORY USAGE cache:large:object# Configure max memory policyCONFIG SET maxmemory 2gbCONFIG SET maxmemory-policy allkeys-lruTransactions and Atomicity
MULTI/EXEC Transactions
# Transaction blockMULTIINCR stats:viewsLPUSH recent:views "page:123"EXEC# Watch for optimistic lockingWATCH user:1234:balancebalance = GET user:1234:balanceMULTISET user:1234:balance (balance - 100)EXECLua Scripts
- Use for complex atomic operations
- Scripts execute atomically
-- Rate limiting scriptlocal 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 0endredis.call('INCR', key)if current == 0 then redis.call('EXPIRE', key, window)endreturn 1
# Execute Lua scriptEVAL "return redis.call('GET', KEYS[1])" 1 mykeyPub/Sub and Messaging
# PublisherPUBLISH channel:notifications '{"type":"alert","message":"New order"}'# SubscriberSUBSCRIBE channel:notifications# Pattern subscriptionPSUBSCRIBE channel:*High Availability
Replication
- Use replicas for read scaling
- Configure proper persistence on master
# On replicaREPLICAOF master_host 6379# Check replication statusINFO replicationRedis Sentinel
- Use for automatic failover
- Deploy at least 3 Sentinel instances
Redis Cluster
- Use for horizontal scaling
- Data automatically sharded across nodes
- Use hash tags for related keys
# Hash tags ensure keys go to same slotSET {user:1234}:profile "data"SET {user:1234}:settings "data"Persistence
RDB Snapshots
# Manual snapshotBGSAVE# Configure automatic snapshotsCONFIG SET save "900 1 300 10 60 10000"AOF (Append-Only File)
# Enable AOFCONFIG SET appendonly yesCONFIG SET appendfsync everysec# Rewrite AOFBGREWRITEAOFSecurity
- Require authentication
- Use TLS for connections
- Bind to specific interfaces
- Disable dangerous commands
# Set passwordCONFIG SET requirepass "your_strong_password"# AuthenticateAUTH your_strong_password# Rename dangerous commands (in redis.conf)rename-command FLUSHALL ""rename-command FLUSHDB ""rename-command KEYS ""Monitoring
# Server infoINFO# Memory statsINFO memory# Client connectionsCLIENT LIST# Slow logSLOWLOG GET 10# Monitor commands (debug only)MONITOR# Key count per databaseINFO keyspaceConnection Management
- Use connection pooling
- Set appropriate timeouts
- Handle reconnection gracefully
# Python example with connection poolimport redispool = redis.ConnectionPool( host='localhost', port=6379, max_connections=50, socket_timeout=5, socket_connect_timeout=5)redis_client = redis.Redis(connection_pool=pool)
Performance Tips
- Use pipelining for batch operations
- Avoid large keys (>100KB values)
- Use SCAN instead of KEYS in production
- Monitor and optimize memory usage
- Consider using RedisJSON for complex JSON operations
# Pipeline example (pseudo-code)pipe = redis.pipeline()pipe.get("key1")pipe.get("key2")pipe.set("key3", "value")results = pipe.execute() 安裝 redis-best-practices
請下載並將技能檔案解壓縮至您的 .claude/skills/ 目錄中。
下載 ZIP複製儲存庫並將技能檔案複製到您的專案中。
git clone https://github.com/Mindrally/skills/blob/main/redis-best-practices/SKILL.md # Copy SKILL.md to your .claude/skills/ directory
複製





首頁
