{"slug":"cache-replicas","title":"Redis Replicas","description":"Redis replicas provide high availability, improved read performance, and automatic failover for your managed Redis instances. This guide covers replica configuration, management, and best practices.","section":"Features","url":"https://docs.danubedata.ro/cache-replicas","markdown_url":"https://docs.danubedata.ro/cache-replicas.md","breadcrumbs":[{"title":"Features","slug":null},{"title":"Cache","slug":"cache-overview"},{"title":"Redis Replicas","slug":"cache-replicas"}],"headings":[{"level":1,"title":"Redis Replicas","id":"redis-replicas"},{"level":2,"title":"Overview","id":"overview"},{"level":2,"title":"How Redis Replication Works","id":"how-redis-replication-works"},{"level":3,"title":"Replication Architecture","id":"replication-architecture"},{"level":3,"title":"Replication Process","id":"replication-process"},{"level":3,"title":"Replication Lag","id":"replication-lag"},{"level":2,"title":"Creating Replicas","id":"creating-replicas"},{"level":3,"title":"Prerequisites","id":"prerequisites"},{"level":3,"title":"Via Dashboard","id":"via-dashboard"},{"level":3,"title":"Replica Configuration","id":"replica-configuration"},{"level":4,"title":"Replica Placement","id":"replica-placement"},{"level":2,"title":"Connecting to Replicas","id":"connecting-to-replicas"},{"level":3,"title":"Connection Endpoints","id":"connection-endpoints"},{"level":3,"title":"Read-Only Access","id":"read-only-access"},{"level":3,"title":"Application Configuration","id":"application-configuration"},{"level":4,"title":"Python with Read/Write Splitting","id":"python-with-readwrite-splitting"},{"level":4,"title":"Laravel Configuration","id":"laravel-configuration"},{"level":4,"title":"Node.js with Failover","id":"nodejs-with-failover"},{"level":2,"title":"High Availability Configuration","id":"high-availability-configuration"},{"level":3,"title":"Automatic Failover","id":"automatic-failover"},{"level":3,"title":"Failover Process","id":"failover-process"},{"level":3,"title":"Manual Failover","id":"manual-failover"},{"level":3,"title":"Handling Failover in Applications","id":"handling-failover-in-applications"},{"level":4,"title":"Connection Retry Logic","id":"connection-retry-logic"},{"level":4,"title":"Circuit Breaker Pattern","id":"circuit-breaker-pattern"},{"level":2,"title":"Monitoring Replicas","id":"monitoring-replicas"},{"level":3,"title":"Key Metrics","id":"key-metrics"},{"level":3,"title":"Redis Commands","id":"redis-commands"},{"level":3,"title":"Monitoring Script","id":"monitoring-script"},{"level":2,"title":"Replica Management","id":"replica-management"},{"level":3,"title":"Scaling Read Capacity","id":"scaling-read-capacity"},{"level":3,"title":"Resizing Replicas","id":"resizing-replicas"},{"level":3,"title":"Removing Replicas","id":"removing-replicas"},{"level":2,"title":"Synchronous Replication","id":"synchronous-replication"},{"level":3,"title":"Enabling Synchronous Replication","id":"enabling-synchronous-replication"},{"level":3,"title":"How It Works","id":"how-it-works"},{"level":3,"title":"Trade-offs","id":"trade-offs"},{"level":2,"title":"Best Practices","id":"best-practices"},{"level":3,"title":"Application Design","id":"application-design"},{"level":3,"title":"Scaling Strategy","id":"scaling-strategy"},{"level":3,"title":"High Availability","id":"high-availability"},{"level":3,"title":"Performance","id":"performance"},{"level":2,"title":"Troubleshooting","id":"troubleshooting"},{"level":3,"title":"High Replication Lag","id":"high-replication-lag"},{"level":3,"title":"Replica Connection Failures","id":"replica-connection-failures"},{"level":3,"title":"Replica Out of Sync","id":"replica-out-of-sync"},{"level":3,"title":"Failover Not Working","id":"failover-not-working"},{"level":2,"title":"Related Documentation","id":"related-documentation"}],"format":"markdown","word_count":1856,"content":"# Redis Replicas\n\nRedis replicas provide high availability, improved read performance, and automatic failover for your managed Redis instances. This guide covers replica configuration, management, and best practices.\n\n> The same replica model applies to **Valkey** instances (Valkey is Redis-compatible). **Dragonfly** instances run as a single standalone node (no read replicas).\n\n## Overview\n\nRedis replicas create read-only copies of your primary Redis instance:\n\n- **High Availability**: Automatic failover if primary fails\n- **Read Scaling**: Distribute read operations across replicas\n- **Disaster Recovery**: Maintain standby instance for recovery\n- **Zero Data Loss**: Synchronous replication available\n- **Automatic Promotion**: Replica automatically becomes primary on failure\n\n## How Redis Replication Works\n\n### Replication Architecture\n\n```\n┌─────────────┐        Async/Sync Replication      ┌─────────────┐\n│   Primary   │ ────────────────────────────────> │   Replica   │\n│ (Read/Write)│                                    │ (Read-Only) │\n└─────────────┘                                    └─────────────┘\n       │                                                    │\n       │                                                    │\n  Write Ops                                           Read Ops\n```\n\n### Replication Process\n\n1. **Initial Sync**: Replica requests full copy from primary\n2. **RDB Transfer**: Primary sends snapshot to replica\n3. **Command Stream**: Primary streams write commands to replica\n4. **Apply Commands**: Replica applies commands in order\n5. **Stay Synchronized**: Continuous replication of all writes\n\n### Replication Lag\n\n- **Asynchronous**: Typically < 10ms lag\n- **Synchronous**: Zero lag (available for critical data)\n- **Monitoring**: Lag displayed in dashboard\n- **Automatic Catch-up**: Replicas automatically sync after disconnection\n\n## Creating Replicas\n\n### Prerequisites\n\n- Existing Redis instance (primary)\n- Instance must be in healthy state\n- Sufficient account limits for additional resources\n\n### Via Dashboard\n\n1. Navigate to your Redis instance\n2. Click **Replicas** tab\n3. Click **Create Replica**\n4. Configure replica:\n   - **Name**: Descriptive name\n   - **Placement**: Same datacenter as primary, on a separate host\n   - **Profile**: Match or differ from primary\n   - **Replication Mode**: Asynchronous or Synchronous\n5. Click **Create**\n\nReplica will be ready within 2-5 minutes.\n\n### Replica Configuration\n\n#### Replica Placement\n\nReplicas run in the same datacenter as the primary, on a separate host.\n\n**Best for**:\n- High availability\n- Read scaling\n- Minimal replication lag (< 10ms)\n- Lower cost\n\n## Connecting to Replicas\n\n### Connection Endpoints\n\nEach replica has its own endpoint:\n\n```\nPrimary:   redis-123456.danubedata.ro:6379\nReplica 1: redis-replica-123456-01.danubedata.ro:6379\nReplica 2: redis-replica-123456-02.danubedata.ro:6379\n```\n\n### Read-Only Access\n\nReplicas are read-only by default:\n\n```python\nimport redis\n\n# Primary - read/write\nprimary = redis.Redis(\n    host='redis-123456.danubedata.ro',\n    port=6379,\n    password='password',\n    ssl=True\n)\n\n# Replica - read-only\nreplica = redis.Redis(\n    host='redis-replica-123456-01.danubedata.ro',\n    port=6379,\n    password='password',\n    ssl=True\n)\n\n# Writes go to primary\nprimary.set('key', 'value')  # ✓ Works\n\n# Reads can use replica\nvalue = replica.get('key')  # ✓ Works\n\n# Writes to replica will fail\nreplica.set('key', 'value')  # ✗ Error: READONLY\n```\n\n### Application Configuration\n\n#### Python with Read/Write Splitting\n\n```python\nfrom redis import Redis\nimport random\n\nclass RedisClient:\n    def __init__(self, primary_host, replica_hosts):\n        self.primary = Redis(host=primary_host, ssl=True, ...)\n        self.replicas = [Redis(host=host, ssl=True, ...) for host in replica_hosts]\n    \n    def get_replica(self):\n        \"\"\"Get random replica for load balancing\"\"\"\n        return random.choice(self.replicas) if self.replicas else self.primary\n    \n    def get(self, key):\n        \"\"\"Read from replica\"\"\"\n        return self.get_replica().get(key)\n    \n    def set(self, key, value, **kwargs):\n        \"\"\"Write to primary\"\"\"\n        return self.primary.set(key, value, **kwargs)\n    \n    def delete(self, key):\n        \"\"\"Delete from primary\"\"\"\n        return self.primary.delete(key)\n\n# Usage\nredis_client = RedisClient(\n    primary_host='redis-123456.danubedata.ro',\n    replica_hosts=[\n        'redis-replica-123456-01.danubedata.ro',\n        'redis-replica-123456-02.danubedata.ro',\n    ]\n)\n\n# Writes to primary\nredis_client.set('user:1000', 'John')\n\n# Reads from replica\nuser = redis_client.get('user:1000')\n```\n\n#### Laravel Configuration\n\n```php\n// config/database.php\n'redis' => [\n    'client' => env('REDIS_CLIENT', 'phpredis'),\n    \n    'options' => [\n        'cluster' => env('REDIS_CLUSTER', 'redis'),\n        'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),\n    ],\n\n    'default' => [\n        'url' => env('REDIS_URL'),\n        'host' => env('REDIS_HOST', 'redis-123456.danubedata.ro'),\n        'password' => env('REDIS_PASSWORD', null),\n        'port' => env('REDIS_PORT', '6379'),\n        'database' => env('REDIS_DB', '0'),\n        'read_write_timeout' => 60,\n        'context' => [\n            'stream' => [\n                'verify_peer' => true,\n                'verify_peer_name' => true,\n            ],\n        ],\n    ],\n\n    'replica' => [\n        'url' => env('REDIS_REPLICA_URL'),\n        'host' => env('REDIS_REPLICA_HOST', 'redis-replica-123456-01.danubedata.ro'),\n        'password' => env('REDIS_PASSWORD', null),\n        'port' => env('REDIS_PORT', '6379'),\n        'database' => env('REDIS_DB', '0'),\n        'read_write_timeout' => 60,\n        'context' => [\n            'stream' => [\n                'verify_peer' => true,\n                'verify_peer_name' => true,\n            ],\n        ],\n    ],\n],\n\n// Usage\nuse Illuminate\\Support\\Facades\\Redis;\n\n// Write to primary\nRedis::connection('default')->set('key', 'value');\n\n// Read from replica\n$value = Redis::connection('replica')->get('key');\n```\n\n#### Node.js with Failover\n\n```javascript\nconst Redis = require('ioredis');\n\nconst primary = new Redis({\n  host: 'redis-123456.danubedata.ro',\n  port: 6379,\n  password: 'password',\n  tls: {}\n});\n\nconst replica = new Redis({\n  host: 'redis-replica-123456-01.danubedata.ro',\n  port: 6379,\n  password: 'password',\n  tls: {},\n  retryStrategy(times) {\n    // Failover to primary after 3 attempts\n    if (times > 3) {\n      return null; // Stop retrying\n    }\n    return Math.min(times * 50, 2000);\n  }\n});\n\nclass RedisManager {\n  async get(key) {\n    try {\n      return await replica.get(key);\n    } catch (error) {\n      console.log('Replica failed, using primary');\n      return await primary.get(key);\n    }\n  }\n  \n  async set(key, value) {\n    return await primary.set(key, value);\n  }\n}\n\nmodule.exports = new RedisManager();\n```\n\n## High Availability Configuration\n\n### Automatic Failover\n\nEnable automatic failover for production instances:\n\n1. Navigate to your Redis instance\n2. Click **Settings** > **High Availability**\n3. Enable **Automatic Failover**\n4. Set **Failover Timeout** (default: 45 seconds)\n5. Click **Save**\n\n### Failover Process\n\nWhen primary fails:\n\n1. **Detection**: Health check detects primary failure (45 seconds)\n2. **Verification**: Multiple checks confirm failure\n3. **Promotion**: Best replica promoted to primary\n4. **DNS Update**: Primary endpoint redirected to new primary\n5. **Notification**: Email alert sent to account owners\n6. **Reconnection**: Applications automatically reconnect\n\n**Expected Downtime**: 30-60 seconds for automatic failover\n\n### Manual Failover\n\nTrigger manual failover for maintenance:\n\n1. Navigate to your Redis instance\n2. Click **Replicas** tab\n3. Select replica to promote\n4. Click **Promote to Primary**\n5. Confirm promotion\n\nManual failover completes within seconds.\n\n### Handling Failover in Applications\n\n#### Connection Retry Logic\n\n```python\nimport redis\nimport time\nfrom redis.exceptions import ConnectionError\n\ndef redis_operation_with_retry(func, *args, max_retries=3, **kwargs):\n    \"\"\"Execute Redis operation with retry logic\"\"\"\n    for attempt in range(max_retries):\n        try:\n            return func(*args, **kwargs)\n        except ConnectionError as e:\n            if attempt == max_retries - 1:\n                raise\n            time.sleep(2 ** attempt)  # Exponential backoff\n            # Recreate connection\n            func.im_self.connection_pool.reset()\n\n# Usage\ntry:\n    redis_operation_with_retry(redis_client.get, 'key')\nexcept ConnectionError:\n    # Handle permanent failure\n    pass\n```\n\n#### Circuit Breaker Pattern\n\n```javascript\nclass CircuitBreaker {\n  constructor(redis, options = {}) {\n    this.redis = redis;\n    this.failures = 0;\n    this.threshold = options.threshold || 5;\n    this.timeout = options.timeout || 60000;\n    this.state = 'CLOSED'; // CLOSED, OPEN, HALF_OPEN\n  }\n  \n  async execute(operation) {\n    if (this.state === 'OPEN') {\n      if (Date.now() - this.openedAt > this.timeout) {\n        this.state = 'HALF_OPEN';\n      } else {\n        throw new Error('Circuit breaker is OPEN');\n      }\n    }\n    \n    try {\n      const result = await operation();\n      this.onSuccess();\n      return result;\n    } catch (error) {\n      this.onFailure();\n      throw error;\n    }\n  }\n  \n  onSuccess() {\n    this.failures = 0;\n    if (this.state === 'HALF_OPEN') {\n      this.state = 'CLOSED';\n    }\n  }\n  \n  onFailure() {\n    this.failures++;\n    if (this.failures >= this.threshold) {\n      this.state = 'OPEN';\n      this.openedAt = Date.now();\n    }\n  }\n}\n```\n\n## Monitoring Replicas\n\n### Key Metrics\n\nMonitor these metrics for replicas:\n\n- **Replication Lag**: Time/bytes behind primary\n- **Connected Replicas**: Number of connected replicas\n- **Replication Offset**: Bytes replicated\n- **Replica Health**: Overall replica status\n- **Connection Count**: Client connections per replica\n- **Memory Usage**: Memory consumption per replica\n\n### Redis Commands\n\nCheck replication status:\n\n```bash\n# On primary\nINFO replication\n\n# Output:\n# role:master\n# connected_slaves:2\n# slave0:ip=10.0.1.5,port=6379,state=online,offset=1234567,lag=0\n# slave1:ip=10.0.2.5,port=6379,state=online,offset=1234567,lag=0\n\n# On replica\nINFO replication\n\n# Output:\n# role:slave\n# master_host:redis-123456.danubedata.ro\n# master_port:6379\n# master_link_status:up\n# master_last_io_seconds_ago:0\n# master_sync_in_progress:0\n```\n\n### Monitoring Script\n\n```python\nimport redis\n\ndef check_replication_health(primary_host, replica_hosts):\n    \"\"\"Check replication health for all replicas\"\"\"\n    primary = redis.Redis(host=primary_host, ...)\n    \n    # Get primary info\n    primary_info = primary.info('replication')\n    print(f\"Primary: {primary_info['role']}\")\n    print(f\"Connected replicas: {primary_info['connected_slaves']}\")\n    \n    # Check each replica\n    for i, replica_host in enumerate(replica_hosts):\n        try:\n            replica = redis.Redis(host=replica_host, ...)\n            info = replica.info('replication')\n            \n            print(f\"\\nReplica {i+1}:\")\n            print(f\"  Status: {info['master_link_status']}\")\n            print(f\"  Lag: {info['master_last_io_seconds_ago']}s\")\n            print(f\"  Sync in progress: {info['master_sync_in_progress']}\")\n        except Exception as e:\n            print(f\"\\nReplica {i+1}: ERROR - {e}\")\n\n# Run check\ncheck_replication_health(\n    'redis-123456.danubedata.ro',\n    ['redis-replica-123456-01.danubedata.ro', \n     'redis-replica-123456-02.danubedata.ro']\n)\n```\n\n## Replica Management\n\n### Scaling Read Capacity\n\nAdd more replicas to scale reads:\n\n1. Create additional replicas\n2. Update application configuration with new endpoints\n3. Implement load balancing across all replicas\n4. Monitor distribution of read traffic\n\n### Resizing Replicas\n\nChange replica resource profile:\n\n1. Navigate to replica in dashboard\n2. Click **Resize**\n3. Select new profile\n4. Confirm resize\n\n> **Note**: Replica can have different profile than primary\n\n### Removing Replicas\n\nDelete unused replicas:\n\n1. Navigate to replica in dashboard\n2. Click **Delete**\n3. Confirm deletion\n4. Update application configuration to remove endpoint\n\n## Synchronous Replication\n\nFor critical data requiring zero data loss:\n\n### Enabling Synchronous Replication\n\n1. Navigate to your Redis instance\n2. Click **Settings** > **Replication**\n3. Enable **Synchronous Replication**\n4. Set **Minimum Replicas** (e.g., 1)\n5. Click **Save**\n\n### How It Works\n\nWith synchronous replication:\n\n- Write operations wait for acknowledgment from replicas\n- Guarantees zero data loss on failover\n- Higher latency for write operations (typically +5-10ms)\n- Write fails if minimum replicas not available\n\n### Trade-offs\n\n**Pros**:\n- Zero data loss guarantee\n- Strong consistency\n- Perfect for financial/critical data\n\n**Cons**:\n- Increased write latency\n- Reduced write throughput\n- Availability depends on replica health\n\n## Best Practices\n\n### Application Design\n\n1. **Separate Connections**: Use different connections for primary and replicas\n2. **Read from Replicas**: Route all read traffic to replicas when possible\n3. **Write to Primary**: Always write to primary\n4. **Handle Failover**: Implement retry logic with exponential backoff\n5. **Connection Pooling**: Use pools for both primary and replica connections\n\n### Scaling Strategy\n\n1. **Start with One Replica**: Provide high availability\n2. **Add Replicas for Reads**: Scale horizontally as needed\n3. **Separate Hosts**: Replicas run on separate physical hosts for resilience\n4. **Monitor Load**: Watch primary and replica utilization\n5. **Load Balance**: Distribute reads evenly across replicas\n\n### High Availability\n\n1. **Enable Auto-Failover**: Critical for production\n2. **Multiple Replicas**: At least 2 for redundancy\n3. **Separate Hosts**: Replicas run on separate physical hosts within the datacenter\n4. **Regular Testing**: Test failover procedures monthly\n5. **Monitoring and Alerts**: Set up alerts for replication lag\n\n### Performance\n\n1. **Connection Pooling**: Reuse connections efficiently\n2. **Pipeline Commands**: Batch operations when possible\n3. **Monitor Lag**: Keep replication lag under 100ms\n4. **Right-Size Resources**: Ensure replicas have adequate resources\n5. **Network Proximity**: Place replicas close to application servers\n\n## Troubleshooting\n\n### High Replication Lag\n\n**Symptoms**: Replica falling behind primary\n\n**Causes**:\n- High write load on primary\n- Network bandwidth limitations\n- Undersized replica resources\n- Large bulk operations\n\n**Solutions**:\n- Upgrade replica to larger profile\n- Optimize write operations on primary\n- Split large operations into smaller batches\n- Check network connectivity\n- Monitor primary CPU/memory usage\n\n### Replica Connection Failures\n\n**Symptoms**: Cannot connect to replica\n\n**Solutions**:\n- Check replica status in dashboard\n- Verify connection details and credentials\n- Test with redis-cli\n- Check firewall rules\n- Review application logs for errors\n\n### Replica Out of Sync\n\n**Symptoms**: Replication status shows \"sync_in_progress\" or \"disconnected\"\n\n**Solutions**:\n- Check primary and replica health\n- Verify network connectivity\n- Review replication logs in dashboard\n- Rebuild replica if necessary\n- Contact support if issue persists\n\n### Failover Not Working\n\n**Symptoms**: Primary fails but replica not promoted\n\n**Causes**:\n- Auto-failover not enabled\n- No healthy replicas available\n- Replication lag too high\n- Network partitioning\n\n**Solutions**:\n- Verify auto-failover is enabled\n- Check replica health status\n- Ensure replicas are online and synced\n- Manually promote replica if needed\n- Review failover logs\n\n## Related Documentation\n\n- [Redis Overview](https://docs.danubedata.ro/cache-redis)\n- [Cache Overview](https://docs.danubedata.ro/cache-overview)\n- [Cache Persistence](https://docs.danubedata.ro/cache-persistence)\n- [Cache Monitoring](https://docs.danubedata.ro/cache-monitoring)\n- [High Availability Best Practices](https://docs.danubedata.ro/platform-sla)\n\n","prev":{"title":"Redis","slug":"cache-redis","url":"https://docs.danubedata.ro/cache-redis","markdown_url":"https://docs.danubedata.ro/cache-redis.md","json_url":"https://docs.danubedata.ro/cache-redis.json"},"next":{"title":"Persistence","slug":"cache-persistence","url":"https://docs.danubedata.ro/cache-persistence","markdown_url":"https://docs.danubedata.ro/cache-persistence.md","json_url":"https://docs.danubedata.ro/cache-persistence.json"},"index_url":"https://docs.danubedata.ro/index.json"}