redis-best-practices
mindrally/skills
캐싱, 데이터 구조 및 고성능 키-값 연산을 위한 Redis 개발 모범 사례
...모든 것을 확장하십시오소개 redis-best-practices
'Redis 모범 사례' 스킬은 Redis를 인메모리 데이터 스토어로 효과적으로 활용하기 위한 포괄적인 지침을 제공합니다. 이 스킬은 캐싱, 세션 저장, 실시간 분석, 메시지 큐잉을 위한 최적의 패턴을 다루며, 개발자가 흔히 발생하는 함정과 성능 문제를 피할 수 있도록 돕습니다. 이 스킬은 확장성과 유지 관리성을 보장하는 적절한 데이터 구조 선택, 키 명명 규칙, 아키텍처 패턴을 가르침으로써 Redis의 잠재력을 최대한 활용하는 데 따르는 과제를 해결합니다.
이 스킬은 Redis의 5가지 핵심 데이터 구조(문자열, 해시, 리스트, 세트, 정렬된 세트)와 이벤트 처리를 위한 새로운 스트림 기능에 중점을 둡니다. 각 구조에 대한 실용적인 코드 예제를 제공하며, 원자적 연산, 일괄 명령어, 차단 연산을 언제 어떻게 사용해야 하는지 보여줍니다. 주요 주제에는 효율적인 캐시-어사이드(cache-aside) 패턴 구현, 정렬된 집합을 활용한 리더보드 설계, 리스트를 이용한 메시지 큐 구축, 컨슈머 그룹을 통한 분산 이벤트 처리 등이 포함됩니다. 이 가이드에서는 메모리 효율성, 적절한 만료 정책, Redis 애플리케이션의 디버깅과 확장을 용이하게 하는 일관된 명명 규칙을 강조합니다.
이 스킬은 빠른 데이터 액세스가 필요한 고성능 애플리케이션을 다루는 백엔드 개발자, 캐싱 계층을 설계하는 DevOps 엔지니어, 실시간 시스템을 구축하는 아키텍트에게 이상적입니다. 세션 관리를 구현하거나, 속도 제한기를 구축하거나, 활동 피드를 생성하거나, 분산 작업 큐를 설계하는 등 어떤 작업을 하든, 이 스킬은 프로덕션 시스템에 직접 적용할 수 있는 실전에서 검증된 패턴과 구체적인 예시를 제공합니다.
자주 묻는 질문
순위표에는 어떤 데이터 구조를 사용해야 할까요?
점수가 플레이어 순위를 나타내는 경우, 정렬된 집합(ZADD, ZREVRANGE)을 사용하세요. 정렬된 집합은 순서를 자동으로 유지하며, 효율적인 순위 쿼리와 점수 기반 범위 연산을 지원합니다.
적절한 캐시 만료 기간을 구현하려면 어떻게 해야 합니까?
SET 명령어의 EX 매개변수를 사용하여 만료 시간을 설정하거나 SETEX를 사용하세요. 데이터의 변동성에 따라 TTL 값을 선택하세요. 자주 변경되는 데이터의 경우 더 짧은 시간(초~분), 정적 콘텐츠의 경우 더 긴 시간(시간~일)을 설정하세요.
여러 개의 문자열 키 대신 해시를 언제 사용해야 하나요?
여러 필드를 가진 객체를 저장할 때는 해시를 사용하십시오. 해시는 각 필드마다 별도의 문자열 키를 생성하는 것보다 메모리 효율이 높으며, 전체 객체를 불러오지 않고도 부분 업데이트가 가능합니다.
큐에서 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
복사





집
