Initial commit
This commit is contained in:
474
docs/REDIS_PERFORMANCE_GUIDE.md
Normal file
474
docs/REDIS_PERFORMANCE_GUIDE.md
Normal file
@@ -0,0 +1,474 @@
|
||||
# Redis Performance Benchmarking Guide
|
||||
|
||||
## Overview
|
||||
|
||||
This guide helps you verify and measure the performance improvements achieved with Redis caching.
|
||||
|
||||
## Quick Performance Check
|
||||
|
||||
### 1. Monitor Cache Hits in Real-time
|
||||
|
||||
```bash
|
||||
# Terminal 1: Start monitoring Redis
|
||||
redis-cli MONITOR
|
||||
|
||||
# Terminal 2: Make API calls
|
||||
curl http://localhost:3000/api/admin/setup
|
||||
curl http://localhost:3000/api/admin/setup # Second call should be instant
|
||||
|
||||
# Terminal 1: You should see Redis operations
|
||||
# GET admin:setup (cache hit)
|
||||
```
|
||||
|
||||
### 2. Check Cache Statistics
|
||||
|
||||
```bash
|
||||
# Get Redis stats
|
||||
redis-cli INFO stats
|
||||
|
||||
# Key metrics:
|
||||
# - total_commands_processed: Total Redis commands
|
||||
# - instantaneous_ops_per_sec: Operations per second
|
||||
# - keyspace_hits: Successful cache hits
|
||||
# - keyspace_misses: Cache misses (DB queries needed)
|
||||
|
||||
# Calculate hit rate
|
||||
redis-cli INFO stats | grep "keyspace"
|
||||
|
||||
# Output example:
|
||||
# keyspace_hits:1000 (cached responses)
|
||||
# keyspace_misses:200 (database queries)
|
||||
# Hit rate = 1000 / (1000 + 200) = 83%
|
||||
```
|
||||
|
||||
### 3. List All Cached Data
|
||||
|
||||
```bash
|
||||
# See all cache keys
|
||||
redis-cli KEYS "*"
|
||||
|
||||
# See specific cache types
|
||||
redis-cli KEYS "session:*" # All sessions
|
||||
redis-cli KEYS "user:*" # All cached users
|
||||
redis-cli KEYS "admin:setup" # Admin configuration
|
||||
redis-cli KEYS "webinar:*" # Webinar data
|
||||
|
||||
# Get cache size in memory
|
||||
redis-cli INFO memory
|
||||
# Look for "used_memory_human" for actual usage
|
||||
```
|
||||
|
||||
## Performance Testing Steps
|
||||
|
||||
### Test 1: Admin Setup Page Performance
|
||||
|
||||
```bash
|
||||
# Baseline (without cache - first request)
|
||||
time curl http://localhost:3000/api/admin/setup
|
||||
|
||||
# Example output without cache:
|
||||
# real 0m0.234s (234ms)
|
||||
|
||||
# With cache (second request)
|
||||
time curl http://localhost:3000/api/admin/setup
|
||||
|
||||
# Example output with cache:
|
||||
# real 0m0.005s (5ms)
|
||||
|
||||
# Performance improvement: ~98% faster
|
||||
```
|
||||
|
||||
### Test 2: Session Lookup Performance
|
||||
|
||||
```bash
|
||||
# Login to get a session
|
||||
curl -c cookies.txt -X POST http://localhost:3000/api/auth/signin \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"email":"user@example.com","password":"password"}'
|
||||
|
||||
# Measure session verification (first call - cache miss)
|
||||
time curl -b cookies.txt http://localhost:3000/api/auth/me
|
||||
|
||||
# Example: ~100-150ms
|
||||
|
||||
# Measure session verification (subsequent calls - cache hit)
|
||||
time curl -b cookies.txt http://localhost:3000/api/auth/me
|
||||
time curl -b cookies.txt http://localhost:3000/api/auth/me
|
||||
time curl -b cookies.txt http://localhost:3000/api/auth/me
|
||||
|
||||
# Example: ~5-10ms each
|
||||
```
|
||||
|
||||
### Test 3: Database Query Reduction
|
||||
|
||||
```bash
|
||||
# Get baseline stats
|
||||
redis-cli INFO stats > stats_before.txt
|
||||
|
||||
# Make 100 API calls
|
||||
for i in {1..100}; do
|
||||
curl http://localhost:3000/api/admin/setup
|
||||
done
|
||||
|
||||
# Get updated stats
|
||||
redis-cli INFO stats > stats_after.txt
|
||||
|
||||
# Compare
|
||||
diff stats_before.txt stats_after.txt
|
||||
|
||||
# Calculate improvements:
|
||||
# - Before: 100 database queries (100% hit DB)
|
||||
# - After: ~2 database queries (cache hits for remaining 98)
|
||||
# - Improvement: 98% reduction in database load
|
||||
```
|
||||
|
||||
### Test 4: Concurrent User Performance
|
||||
|
||||
```bash
|
||||
# Install Apache Bench (if not installed)
|
||||
# macOS: brew install httpd
|
||||
# Linux: apt-get install apache2-utils
|
||||
|
||||
# Test with 10 concurrent users, 100 requests total
|
||||
ab -n 100 -c 10 http://localhost:3000/api/admin/setup
|
||||
|
||||
# Key metrics in output:
|
||||
# Requests per second: [RPS] <- Higher is better
|
||||
# Time per request: [ms] <- Lower is better
|
||||
# Failed requests: 0 <- Should be zero
|
||||
|
||||
# Expected results with cache:
|
||||
# Requests per second: 150-300 (vs 20-50 without cache)
|
||||
# Time per request: 30-50ms (vs 200-500ms without cache)
|
||||
```
|
||||
|
||||
## Cache Hit Rate Analysis
|
||||
|
||||
### Calculate Hit Rate
|
||||
|
||||
```bash
|
||||
# Get stats
|
||||
STATS=$(redis-cli INFO stats)
|
||||
|
||||
# Extract hit and miss counts
|
||||
HITS=$(echo "$STATS" | grep "keyspace_hits" | cut -d: -f2 | tr -d '\r')
|
||||
MISSES=$(echo "$STATS" | grep "keyspace_misses" | cut -d: -f2 | tr -d '\r')
|
||||
|
||||
# Calculate rate (shell math)
|
||||
TOTAL=$((HITS + MISSES))
|
||||
if [ $TOTAL -gt 0 ]; then
|
||||
RATE=$((HITS * 100 / TOTAL))
|
||||
echo "Cache Hit Rate: ${RATE}%"
|
||||
echo "Hits: $HITS"
|
||||
echo "Misses: $MISSES"
|
||||
fi
|
||||
```
|
||||
|
||||
### Interpret Results
|
||||
|
||||
| Hit Rate | Performance | Action |
|
||||
|----------|-------------|--------|
|
||||
| 90%+ | Excellent | No action needed |
|
||||
| 75-90% | Good | Monitor, consider increasing TTL |
|
||||
| 50-75% | Fair | Review cache keys, optimize patterns |
|
||||
| <50% | Poor | Check Redis connection, review cache strategy |
|
||||
|
||||
## Memory Usage Analysis
|
||||
|
||||
```bash
|
||||
# Check Redis memory
|
||||
redis-cli INFO memory
|
||||
|
||||
# Key values:
|
||||
# used_memory: Bytes used
|
||||
# used_memory_human: Human readable format
|
||||
# used_memory_peak: Peak memory used
|
||||
# maxmemory: Max allowed memory
|
||||
# memory_fragmentation_ratio: Should be < 1.5
|
||||
|
||||
# Set memory limit (optional)
|
||||
# redis-cli CONFIG SET maxmemory 512mb
|
||||
# redis-cli CONFIG SET maxmemory-policy allkeys-lru
|
||||
```
|
||||
|
||||
## Load Testing Scenarios
|
||||
|
||||
### Scenario 1: Peak Hour Traffic
|
||||
|
||||
```bash
|
||||
# Simulate peak hour (1000 requests in 10 seconds)
|
||||
for i in {1..1000}; do
|
||||
curl http://localhost:3000/api/admin/setup &
|
||||
if [ $((i % 50)) -eq 0 ]; then
|
||||
sleep 0.5
|
||||
fi
|
||||
done
|
||||
wait
|
||||
|
||||
# Monitor during test
|
||||
redis-cli MONITOR
|
||||
redis-cli INFO stats
|
||||
|
||||
# Expected: High RPS, low latency, no errors
|
||||
```
|
||||
|
||||
### Scenario 2: User Login Spike
|
||||
|
||||
```bash
|
||||
# Simulate login spike
|
||||
for i in {1..100}; do
|
||||
curl -X POST http://localhost:3000/api/auth/signin \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"email\":\"user$i@example.com\",\"password\":\"pass\"}" &
|
||||
done
|
||||
wait
|
||||
|
||||
# Check session cache
|
||||
redis-cli KEYS "session:*" | wc -l
|
||||
|
||||
# Should have ~100 sessions cached
|
||||
```
|
||||
|
||||
### Scenario 3: Configuration Updates
|
||||
|
||||
```bash
|
||||
# Monitor cache invalidation
|
||||
redis-cli MONITOR
|
||||
|
||||
# Update admin setup
|
||||
curl -X POST http://localhost:3000/api/admin/setup \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"pagination":{"itemsPerPage":20}}'
|
||||
|
||||
# In monitor, should see:
|
||||
# DEL admin:setup (cache invalidation)
|
||||
# Then fresh cache on next GET
|
||||
```
|
||||
|
||||
## Performance Bottlenecks
|
||||
|
||||
### Identify Slow Operations
|
||||
|
||||
```bash
|
||||
# Enable Redis slowlog
|
||||
redis-cli CONFIG SET slowlog-log-slower-than 10000 # 10ms
|
||||
redis-cli CONFIG SET slowlog-max-len 128
|
||||
|
||||
# View slow commands
|
||||
redis-cli SLOWLOG GET 10
|
||||
|
||||
# Look for:
|
||||
# - O(N) operations on large datasets
|
||||
# - KEYS pattern matching
|
||||
# - Large value sizes
|
||||
```
|
||||
|
||||
### Find Memory Leaks
|
||||
|
||||
```bash
|
||||
# Monitor memory growth
|
||||
redis-cli INFO memory | grep used_memory_human
|
||||
|
||||
# Run for a while (hour), then check again
|
||||
redis-cli INFO memory | grep used_memory_human
|
||||
|
||||
# If constantly growing:
|
||||
# 1. Check for missing TTL
|
||||
# 2. Verify cache invalidation
|
||||
# 3. Review cache key patterns
|
||||
# 4. Use FLUSHALL to reset (dev only)
|
||||
```
|
||||
|
||||
## Optimization Recommendations
|
||||
|
||||
### Based on Hit Rate
|
||||
|
||||
**If hit rate < 90%:**
|
||||
- Increase TTL for frequently accessed data
|
||||
- Check cache key patterns
|
||||
- Verify cache invalidation isn't too aggressive
|
||||
|
||||
**If memory usage > 80% of limit:**
|
||||
- Implement eviction policy (LRU)
|
||||
- Reduce TTL values
|
||||
- Remove unused cache keys
|
||||
|
||||
**If response time > 50ms:**
|
||||
- Verify Redis is on same network/machine
|
||||
- Check Redis memory pressure
|
||||
- Monitor CPU usage
|
||||
- Consider Redis cluster for scale
|
||||
|
||||
### Cache Key Strategy
|
||||
|
||||
```bash
|
||||
# Good cache keys (organized by feature)
|
||||
session:abc123
|
||||
user:user-id-123
|
||||
admin:setup
|
||||
webinar:webinar-id-456
|
||||
webinars:list:page-1
|
||||
|
||||
# Monitor key space
|
||||
redis-cli --bigkeys # Find largest keys
|
||||
redis-cli --scan # Iterate all keys
|
||||
redis-cli DBSIZE # Total keys in DB
|
||||
```
|
||||
|
||||
## Monitoring Commands Reference
|
||||
|
||||
```bash
|
||||
# Real-time monitoring
|
||||
redis-cli MONITOR # All commands in real-time
|
||||
redis-cli INFO # All stats and info
|
||||
redis-cli INFO stats # Stats only
|
||||
|
||||
# Performance metrics
|
||||
redis-cli SLOWLOG GET 10 # 10 slowest commands
|
||||
redis-cli LATENCY LATEST # Latest latency samples
|
||||
redis-cli LATENCY HISTORY # Historical latency
|
||||
|
||||
# Memory analysis
|
||||
redis-cli INFO memory # Memory breakdown
|
||||
redis-cli --bigkeys # Largest keys
|
||||
redis-cli MEMORY STATS # Memory by allocation
|
||||
|
||||
# Cache analysis
|
||||
redis-cli KEYS "*" # All cache keys
|
||||
redis-cli SCAN 0 # Scan keys (no blocking)
|
||||
redis-cli TTL key # Check TTL remaining
|
||||
redis-cli EXPIRE key 3600 # Set new expiration
|
||||
|
||||
# Debugging
|
||||
redis-cli PING # Test connection
|
||||
redis-cli ECHO "test" # Echo test
|
||||
redis-cli SELECT 0 # Select database
|
||||
redis-cli FLUSHDB # Clear current DB (dev only)
|
||||
redis-cli FLUSHALL # Clear all DBs (dev only)
|
||||
```
|
||||
|
||||
## Troubleshooting Performance Issues
|
||||
|
||||
### Issue: Cache Not Improving Performance
|
||||
|
||||
**Diagnostics:**
|
||||
```bash
|
||||
# Check if Redis is being used
|
||||
redis-cli MONITOR
|
||||
curl http://localhost:3000/api/admin/setup
|
||||
# Should see GET admin:setup command
|
||||
|
||||
# Check cache hits
|
||||
redis-cli INFO stats | grep keyspace
|
||||
# Hits should be increasing
|
||||
```
|
||||
|
||||
**Solutions:**
|
||||
1. Verify Redis connection: `redis-cli ping`
|
||||
2. Check TTL: `redis-cli TTL admin:setup`
|
||||
3. Review cache keys: `redis-cli KEYS "admin:*"`
|
||||
4. Check memory: `redis-cli INFO memory`
|
||||
|
||||
### Issue: High Memory Usage
|
||||
|
||||
**Diagnostics:**
|
||||
```bash
|
||||
redis-cli INFO memory
|
||||
redis-cli --bigkeys # Find large keys
|
||||
redis-cli --scan | wc -l # Count keys
|
||||
```
|
||||
|
||||
**Solutions:**
|
||||
1. Implement TTL on all keys
|
||||
2. Reduce TTL values
|
||||
3. Set maxmemory policy: `redis-cli CONFIG SET maxmemory-policy allkeys-lru`
|
||||
4. Clear unused keys: `redis-cli EVAL "return redis.call('del',unpack(redis.call('keys','*')))" 0`
|
||||
|
||||
### Issue: Slow Cache Operations
|
||||
|
||||
**Diagnostics:**
|
||||
```bash
|
||||
redis-cli SLOWLOG GET 10
|
||||
redis-cli LATENCY LATEST
|
||||
```
|
||||
|
||||
**Solutions:**
|
||||
1. Check network latency
|
||||
2. Verify Redis isn't CPU-bound
|
||||
3. Move Redis closer (same machine/container)
|
||||
4. Consider Redis persistence (if enabled, disable AOF rewrite)
|
||||
|
||||
## Baseline Metrics to Track
|
||||
|
||||
Keep these metrics for comparison:
|
||||
|
||||
```bash
|
||||
# Run this command periodically
|
||||
DATE=$(date +%Y-%m-%d\ %H:%M:%S)
|
||||
echo "=== $DATE ===" >> redis_metrics.log
|
||||
redis-cli INFO stats >> redis_metrics.log
|
||||
redis-cli INFO memory >> redis_metrics.log
|
||||
redis-cli DBSIZE >> redis_metrics.log
|
||||
echo "" >> redis_metrics.log
|
||||
|
||||
# Compare over time to identify trends
|
||||
```
|
||||
|
||||
## Performance Report Example
|
||||
|
||||
```
|
||||
Performance Baseline Report
|
||||
===========================
|
||||
Date: 2025-02-03
|
||||
Environment: Docker (Redis 7-alpine)
|
||||
|
||||
Metrics:
|
||||
- Cache Hit Rate: 94.2%
|
||||
- Avg Response Time: 12ms (with cache)
|
||||
- DB Response Time: 150ms (without cache)
|
||||
- Improvement: 92% faster
|
||||
- Memory Usage: 45MB
|
||||
- Concurrent Users Tested: 100
|
||||
- Requests Per Second: 250
|
||||
|
||||
Cache Statistics:
|
||||
- Total Commands: 5,432
|
||||
- Cache Hits: 5,120
|
||||
- Cache Misses: 312
|
||||
- Session Keys: 87
|
||||
- Admin Setup Hits: 1,543
|
||||
|
||||
System Health:
|
||||
- Redis Memory Fragmentation: 1.1 (Good)
|
||||
- Slowlog Commands: 0
|
||||
- Connection Failures: 0
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Monitor Regularly**
|
||||
- Check metrics weekly
|
||||
- Alert on hit rate drops
|
||||
- Track memory trends
|
||||
|
||||
2. **Optimize TTLs**
|
||||
- Session cache: 7 days
|
||||
- User data: 1 hour
|
||||
- Config: 5 minutes
|
||||
- API responses: Based on freshness needs
|
||||
|
||||
3. **Cache Invalidation**
|
||||
- Clear on data updates
|
||||
- Use patterns: `invalidateCachePattern()`
|
||||
- Verify in Redis: `KEYS pattern:*`
|
||||
|
||||
4. **Production Monitoring**
|
||||
- Use CloudWatch, DataDog, or New Relic
|
||||
- Set up alerts for high memory
|
||||
- Monitor connection count
|
||||
- Track command latency
|
||||
|
||||
5. **Scalability**
|
||||
- Single Redis for <1000 concurrent users
|
||||
- Redis Cluster for >1000 users
|
||||
- Redis Sentinel for high availability
|
||||
Reference in New Issue
Block a user