Redis Configuration
Connect to Redis for caching, session storage, real-time analytics, and in-memory data structures.
Connection Parameters
Required Fields
- Host: Redis hostname
- Port: 6379 (default)
Optional Fields
- Password: Optional (for authenticated instances)
- Database Number: Redis DB index (default: 0)
- Use SSL/TLS: Enable for encrypted connections
Configuration Example
When creating a Redis data source, provide the following information:
| Field | Example Value | Notes |
|---|---|---|
| Name | prod-redis | Unique identifier |
| Label | Production Redis | Display name |
| Host | redis.example.com | Redis hostname |
| Port | 6379 | Default Redis port |
| Password | •••••••• | Optional, encrypted |
| Database Number | 0 | Default database |
| Use SSL/TLS | ✓ Enabled | Recommended |
Usage in Applications
Python Example (redis-py)
import os, json
import redis
# Parse STRONGLY_SERVICES environment variable
services = json.loads(os.getenv('STRONGLY_SERVICES', '{}'))
datasources = services.get('datasources', {})
# Get Redis data source
redis_config = datasources['prod-redis']
creds = redis_config['credentials']
# Create Redis connection
r = redis.Redis(
host=creds['host'],
port=creds['port'],
password=creds.get('password'),
db=creds.get('database', 0),
ssl=creds.get('ssl', False),
decode_responses=True # Automatically decode bytes to strings
)
# Basic operations
# Set value
r.set('user:1000', 'John Doe')
# Get value
name = r.get('user:1000')
print(name) # "John Doe"
# Set with expiration (in seconds)
r.setex('session:abc123', 3600, 'session_data')
# Check if key exists
exists = r.exists('user:1000')
# Delete key
r.delete('user:1000')
Python with Connection Pool
import redis
# Create connection pool for better performance
pool = redis.ConnectionPool(
host=creds['host'],
port=creds['port'],
password=creds.get('password'),
db=creds.get('database', 0),
ssl=creds.get('ssl', False),
decode_responses=True,
max_connections=10
)
# Use pool for connections
r = redis.Redis(connection_pool=pool)
Node.js Example (ioredis)
const Redis = require('ioredis');
// Parse STRONGLY_SERVICES environment variable
const services = JSON.parse(process.env.STRONGLY_SERVICES || '{}');
const datasources = services.datasources || {};
// Get Redis data source
const redisConfig = datasources['prod-redis'];
const creds = redisConfig.credentials;
// Create Redis connection
const redis = new Redis({
host: creds.host,
port: creds.port,
password: creds.password || null,
db: creds.database || 0,
tls: creds.ssl ? {} : undefined
});
// Basic operations
// Set value
await redis.set('user:1000', 'John Doe');
// Get value
const name = await redis.get('user:1000');
console.log(name); // "John Doe"
// Set with expiration
await redis.setex('session:abc123', 3600, 'session_data');
// Check if key exists
const exists = await redis.exists('user:1000');
// Delete key
await redis.del('user:1000');
Go Example (go-redis)
package main
import (
"context"
"encoding/json"
"fmt"
"os"
"time"
"github.com/go-redis/redis/v8"
)
func main() {
ctx := context.Background()
// Parse STRONGLY_SERVICES environment variable
var services map[string]interface{}
json.Unmarshal([]byte(os.Getenv("STRONGLY_SERVICES")), &services)
datasources := services["datasources"].(map[string]interface{})
redisConfig := datasources["prod-redis"].(map[string]interface{})
creds := redisConfig["credentials"].(map[string]interface{})
// Create Redis client
rdb := redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%v", creds["host"], creds["port"]),
Password: creds["password"].(string),
DB: int(creds["database"].(float64)),
})
// Basic operations
// Set value
err := rdb.Set(ctx, "user:1000", "John Doe", 0).Err()
if err != nil {
panic(err)
}
// Get value
val, err := rdb.Get(ctx, "user:1000").Result()
if err != nil {
panic(err)
}
fmt.Println(val)
// Set with expiration
err = rdb.Set(ctx, "session:abc123", "session_data", 1*time.Hour).Err()
// Check if key exists
exists, err := rdb.Exists(ctx, "user:1000").Result()
fmt.Printf("Key exists: %v\n", exists)
// Delete key
err = rdb.Del(ctx, "user:1000").Err()
}
Common Redis Operations
String Operations
# Set multiple key-value pairs
r.mset({
'user:1001': 'Alice',
'user:1002': 'Bob'
})
# Get multiple values
values = r.mget('user:1001', 'user:1002')
# Increment counter
r.incr('page:views')
r.incrby('page:views', 10)
# Decrement counter
r.decr('inventory:items')
Hash Operations
# Set hash field
r.hset('user:1000', 'name', 'John Doe')
r.hset('user:1000', 'email', 'john@example.com')
# Set multiple hash fields
r.hmset('user:1000', {
'name': 'John Doe',
'email': 'john@example.com',
'age': 30
})
# Get hash field
name = r.hget('user:1000', 'name')
# Get all hash fields
user = r.hgetall('user:1000')
# Get multiple hash fields
fields = r.hmget('user:1000', 'name', 'email')
List Operations
# Push to list
r.lpush('messages', 'Hello')
r.rpush('messages', 'World')
# Pop from list
message = r.lpop('messages')
# Get list range
messages = r.lrange('messages', 0, -1)
# Get list length
length = r.llen('messages')
Set Operations
# Add to set
r.sadd('tags', 'python', 'redis', 'cache')
# Get all members
tags = r.smembers('tags')
# Check membership
is_member = r.sismember('tags', 'python')
# Remove from set
r.srem('tags', 'cache')
# Set operations
r.sadd('set1', 'a', 'b', 'c')
r.sadd('set2', 'b', 'c', 'd')
intersection = r.sinter('set1', 'set2') # {'b', 'c'}
union = r.sunion('set1', 'set2') # {'a', 'b', 'c', 'd'}
Sorted Set Operations
# Add to sorted set (with scores)
r.zadd('leaderboard', {
'player1': 100,
'player2': 200,
'player3': 150
})
# Get rank
rank = r.zrank('leaderboard', 'player1')
# Get score
score = r.zscore('leaderboard', 'player1')
# Get top scores
top_players = r.zrevrange('leaderboard', 0, 9, withscores=True)
Caching Patterns
Simple Cache
def get_user(user_id):
# Try cache first
cached = r.get(f'user:{user_id}')
if cached:
return json.loads(cached)
# Cache miss - fetch from database
user = fetch_user_from_db(user_id)
# Store in cache (1 hour expiration)
r.setex(f'user:{user_id}', 3600, json.dumps(user))
return user
Cache-Aside Pattern
def get_product(product_id):
cache_key = f'product:{product_id}'
# Check cache
product = r.get(cache_key)
if product:
return json.loads(product)
# Load from database
product = db.query('SELECT * FROM products WHERE id = ?', product_id)
# Update cache
if product:
r.setex(cache_key, 3600, json.dumps(product))
return product
Write-Through Cache
def update_user(user_id, data):
# Update database
db.update('users', user_id, data)
# Update cache immediately
cache_key = f'user:{user_id}'
r.setex(cache_key, 3600, json.dumps(data))
Session Management
# Store session
def create_session(session_id, user_data):
r.setex(
f'session:{session_id}',
3600, # 1 hour expiration
json.dumps(user_data)
)
# Get session
def get_session(session_id):
session = r.get(f'session:{session_id}')
if session:
# Refresh expiration
r.expire(f'session:{session_id}', 3600)
return json.loads(session)
return None
# Delete session (logout)
def delete_session(session_id):
r.delete(f'session:{session_id}')
Pub/Sub Messaging
# Publisher
def publish_message(channel, message):
r.publish(channel, message)
# Subscriber
def subscribe_to_channel(channel):
pubsub = r.pubsub()
pubsub.subscribe(channel)
for message in pubsub.listen():
if message['type'] == 'message':
print(f"Received: {message['data']}")
Common Issues
Connection Refused
- Verify host and port are correct
- Check firewall rules allow connections
- Ensure Redis is running:
redis-cli ping - Check Redis is listening on correct interface in redis.conf
Authentication Failed
- Verify password is correct
- Check Redis configuration requires authentication:
requirepassin redis.conf - Ensure password is set if Redis expects it
NOAUTH Error
- Redis requires authentication but no password provided
- Set password in Redis configuration or provide password in connection
Wrong Database Number
- Redis has 16 databases by default (0-15)
- Verify database number is within range
- Use database 0 if unsure
Connection Timeout
- Check network connectivity
- Verify Redis is not overloaded
- Increase timeout in client configuration
- Check Redis max clients configuration
Best Practices
- Use Connection Pooling: Reuse connections for better performance
- Set Expiration: Always set TTL for cache keys to prevent memory bloat
- Key Naming Convention: Use consistent naming like
prefix:id:field - Enable Persistence: Configure RDB or AOF for data durability
- Monitor Memory: Track memory usage and set
maxmemorypolicy - Use Pipelining: Batch multiple commands for better performance
- Enable SSL/TLS: Use encryption for production environments
- Limit Key Size: Keep keys and values reasonably sized
- Use Appropriate Data Structures: Choose the right data type for your use case
- Handle Connection Errors: Implement retry logic and error handling
Performance Optimization
Pipelining
Execute multiple commands in one round trip:
# Without pipelining (multiple round trips)
for i in range(1000):
r.set(f'key:{i}', f'value:{i}')
# With pipelining (one round trip)
pipe = r.pipeline()
for i in range(1000):
pipe.set(f'key:{i}', f'value:{i}')
pipe.execute()
Transactions
Execute commands atomically:
pipe = r.pipeline()
pipe.multi()
pipe.incr('counter')
pipe.set('last_updated', time.time())
pipe.execute()
Monitoring
Check Connection
# Ping Redis
response = r.ping()
print(f"Redis is {'connected' if response else 'disconnected'}")
# Get server info
info = r.info()
print(f"Version: {info['redis_version']}")
print(f"Used memory: {info['used_memory_human']}")
print(f"Connected clients: {info['connected_clients']}")
Monitor Commands
# Get stats
stats = r.info('stats')
print(f"Total commands processed: {stats['total_commands_processed']}")
print(f"Instantaneous ops/sec: {stats['instantaneous_ops_per_sec']}")