Starting with redis-py 7.0, kvdb-py supports Active-Active database configurations through the KVDBMultiDBClient. This feature is designed for production environments using Redis Enterprise with Active-Active geo-distributed databases.
The multi-database client provides:
- Automatic Failover: Seamlessly switches to backup databases when the active database becomes unhealthy
- Circuit Breakers: Prevents cascading failures by temporarily stopping requests to unhealthy databases
- Health Monitoring: Continuously checks database health with configurable intervals and policies
- Weighted Selection: Prioritizes databases by weight for intelligent failover decisions
- Command Retries: Automatically retries failed commands with exponential backoff
- Auto-Fallback: Returns to higher-priority databases when they recover
pip install 'redis>=7.0' pybreakerThe multidb features require:
- redis-py >= 7.0
- pybreaker (for circuit breaker functionality)
- Redis Enterprise with Active-Active databases or multiple Redis instances
from kvdb.components.multidb import KVDBMultiDBClient
# Create client from URLs with weights
client = KVDBMultiDBClient.from_urls(
urls=[
"redis://primary.example.com:6379/0",
"redis://secondary.example.com:6379/0",
],
weights=[1.0, 0.5], # Primary has higher weight
)
# Initialize (performs health checks and sets up monitoring)
client.initialize()
# Use like a normal Redis client
client.set("key", "value")
value = client.get("key")from kvdb.components.multidb import (
KVDBMultiDBClient,
MultiDbConfig,
DatabaseConfig,
)
config = MultiDbConfig(
databases_config=[
DatabaseConfig(
from_url="redis://db1.example.com:6379/0",
weight=1.0,
health_check_url="redis://db1.example.com:6379/0",
grace_period=30.0, # Circuit breaker grace period
),
DatabaseConfig(
from_url="redis://db2.example.com:6379/0",
weight=0.8,
health_check_url="redis://db2.example.com:6379/0",
),
DatabaseConfig(
from_url="redis://db3.example.com:6379/0",
weight=0.5,
health_check_url="redis://db3.example.com:6379/0",
),
],
# Health check configuration
health_check_interval=10.0, # Check every 10 seconds
health_check_probes=3, # Number of probes for health determination
health_check_probes_delay=1.0, # Delay between probes
# Failover configuration
failover_attempts=3, # Number of failover attempts
failover_delay=1.0, # Delay between attempts
auto_fallback_interval=120.0, # Auto-fallback to primary after 2 minutes
# Failure detection
min_num_failures=5, # Minimum failures before triggering failover
failure_rate_threshold=0.5, # 50% failure rate threshold
failures_detection_window=60.0, # Track failures in 60-second window
)
client = KVDBMultiDBClient(config)
client.initialize()from redis import ConnectionPool
from kvdb.components.multidb import MultiDbConfig, DatabaseConfig, KVDBMultiDBClient
# Create connection pools for better connection management
pool1 = ConnectionPool.from_url("redis://db1.example.com:6379/0", max_connections=50)
pool2 = ConnectionPool.from_url("redis://db2.example.com:6379/0", max_connections=50)
config = MultiDbConfig(
databases_config=[
DatabaseConfig(from_pool=pool1, weight=1.0),
DatabaseConfig(from_pool=pool2, weight=0.5),
]
)
client = KVDBMultiDBClient(config)
client.initialize()from redis import RedisCluster
from kvdb.components.multidb import KVDBMultiDBClient
client = KVDBMultiDBClient.from_urls(
urls=[
"redis://cluster1.example.com:6379/0",
"redis://cluster2.example.com:6379/0",
],
weights=[1.0, 0.5],
client_class=RedisCluster, # Use Redis Cluster
)
client.initialize()Weights determine database priority for active selection:
- Higher weight = higher priority for becoming active
- Used during failover to select the next best database
- Typical pattern: Primary (1.0), Secondary (0.5-0.8), Tertiary (0.3-0.5)
Circuit breakers prevent cascading failures:
- CLOSED: Database is healthy, requests flow normally
- OPEN: Database is unhealthy, requests are blocked
- HALF_OPEN: Testing if database has recovered
The grace_period defines how long to wait before testing recovery.
Continuous health monitoring with configurable policies:
- Probes: Number of health check attempts
- Delay: Time between probe attempts
- Policy: Logic for determining overall health from probe results
When active database fails:
- Circuit breaker opens for the failed database
- Failure detector triggers failover
- Next highest-weighted healthy database becomes active
- Commands are retried on new active database
- Original database is monitored for recovery
After a configured interval, the system checks if higher-weighted databases have recovered and automatically fails back to them.
# Get all databases
databases = client.get_databases()
# Manually set active database
for db, weight in databases:
if weight == 1.0: # Highest weighted
client.set_active_database(db)
break
# Add a new database dynamically
from kvdb.components.multidb import Database
from redis import Redis
new_db = Database(
client=Redis.from_url("redis://new-db.example.com:6379/0"),
circuit=..., # Circuit breaker instance
weight=0.6,
)
client.add_database(new_db)The multidb client dispatches events for monitoring:
from redis.event import EventDispatcher
def on_database_failover(event):
print(f"Failover occurred: {event}")
dispatcher = EventDispatcher()
# Register event handlers as needed
config = MultiDbConfig(
databases_config=[...],
event_dispatcher=dispatcher,
)- Use Health Check URLs: For Redis Enterprise, use the FQDN endpoint for accurate health checks
- Set Appropriate Weights: Reflect geographic or infrastructure preferences
- Configure Timeouts: Set reasonable socket timeouts to detect failures quickly
- Monitor Events: Track failover events for operational awareness
- Test Failover: Regularly test failover scenarios in staging
- Connection Pools: Use connection pools for better resource management
pip install pybreakerUpgrade redis-py:
pip install --upgrade 'redis>=7.0'- Ensure at least one Redis instance is running and accessible
- Check connection URLs are correct
- Verify network connectivity to Redis instances
- Check Redis authentication credentials if using password
- Verify health check URLs are configured correctly
- Check failure detection thresholds are appropriate
- Ensure health check interval is reasonable for your use case
- Monitor circuit breaker states
- The multidb client is marked as experimental in redis-py
- Not all Redis commands may work identically across databases
- Active-Active configurations have eventual consistency characteristics
- Transaction support may be limited across failovers