← Back to Blog

Integrating HAProxy and KeepAlived for Redis Replication

You just learned how to set up a Redis Replication cluster with Master-Slave nodes combined with Redis Sentinel, running failover super smoothly. In your code, you point at the Master node's address to read/write data.

But one fine day, the Master Node drops dead, Sentinel automatically switches Master to another node, and your code breaks with a flood of errors. Your boss yells at you, you're sad, you go online searching for a way to automatically detect the new Master node once the Failover process happens. This post will help you find a solution to that problem.

A quick recap of Redis Replication

Hopefully sometime soon I can write a detailed post about Redis Replication — for now here's a quick summary for anyone who doesn't know it yet. Redis Replication consists of Master and Slave nodes — the Master node handles read-write, the Slave node handles reading and backing up data from the Master. But this alone is pretty ordinary, so people came up with Redis-sentinel too, so that when the Master node goes down, Sentinel automatically finds a suitable Slave node (based on the replica-priority level).

That said, some argue the model above isn't optimal — a more optimal model would be having the Sentinel service split off into its own separate node, in case both the Redis and Sentinel service die together.

Getting into the main part

That's everything about Redis Replication you need to know to move to the next part. The model I'll walk you through in this post looks like the one above. We have a cluster of 2 HAProxy + KeepAlived nodes to find the Master Node in the Redis Replication. So why do we need 2 nodes??? Isn't 1 node enough to find it? True, 1 node is enough to find it, but since Redis has Failover, HAProxy also needs Failover — that's KeepAlived — to avoid a situation where the HAProxy node dies and takes the whole thing down with it. Here, VIP isn't a node but a Virtual IP created for Failover. Users or the Application will access the redis replication through the VIP.

Installing and configuring KeepAlived

In this post I use CentOS, so I install with yum — if you use Ubuntu, use apt, everything else is similar.

Install Keepalived with the command:

yum -y install keepalived

Configure Keepalived on the Master node:

vrrp_script chk_haproxy {
    script "pkill -0 haproxy"
    interval 2
    weight 2
}
vrrp_instance VI_1 {
    interface eth0
    state MASTER
    virtual_router_id 51
    priority 101
    virtual_ipaddress {
        10.5.9.111
    }
    track_script {
        chk_haproxy
    }
}

Configure KeepAlived on the Slave node:

vrrp_script chk_haproxy {
    script "pkill -0 haproxy"
    interval 2
    weight 2
}
vrrp_instance VI_1 {
    interface eth0
    state BACKUP
    virtual_router_id 51
    priority 100
    virtual_ipaddress {
        10.5.9.111
    }
    track_script {
        chk_haproxy
    }
}

Explanation:

vrrp_script chk_haproxy is a script that checks whether the haproxy service is still alive — if the service dies, priority gets reduced and gets handed over to the BACKUP node

interface: the interface where we set up the Virtual IP (use the ifconfig command to check)

state [MASTER/BACKUP]: the node's state

virtual_router_id: this value must be the same across nodes

priority: the node's priority (higher becomes Master)

virtual_ipaddress: the VIP declaration section

track_script: declares the script above

Config to allow binding to the VIP address

echo 'net.ipv4.ip_nonlocal_bind = 1' >> /etc/sysctl.conf

Installing and configuring HAProxy

Install HAProxy with the command:

yum -y install haproxy

Configure on both the Master and Backup nodes

global
    log         127.0.0.1 local2
    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4000
    user        haproxy
    group       haproxy
    daemon
    stats socket /var/lib/haproxy/stats

defaults
    log                     global
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000

listen stats
    bind *:8080
    mode http
    stats enable
    stats uri /stats
    stats realm HAProxy\ Statistics
    stats admin if TRUE

listen redis_clusters
    bind *:6379
    mode tcp
    timeout connect  3h
    timeout server  3h
    timeout client  3h
    option tcp-check
    tcp-check connect                        # Used to connect to the back-end server
    tcp-check send AUTH\ vccloud1\r\n        # Add this line if Redis has a password
    tcp-check send PING\r\n                  # Check the connection
    tcp-check expect string +PONG            # Expect this return output
    tcp-check send info\ replication\r\n     # Get replication info
    tcp-check expect string role:master      # If it returns role master, confirm this is the master node
    tcp-check send QUIT\r\n                  # Exit the connection
    tcp-check expect string +OK              # Expect this return output (can be omitted)
    server redis-cluster-1 10.5.9.198:6379 check inter 1s
    server redis-cluster-2 10.5.9.105:6379 check inter 1s
    server redis-cluster-3 10.5.10.126:6379 check inter 1s

Explanation:

The global and defaults blocks contain global config, kept as-is.

The Listen stats block creates a status-monitoring page for nodes on port 8080, path /stats

The redis_clusters block

  • bind *:6379; Allows access from any IP
  • mode: the protocol used
  • tcp-check: used to send tcp commands to the back-end server to find the master node
  • server: declares the back-end Redis Cluster Servers

So we've finished installing and configuring KeepAlived + HAProxy — now let's start the services:

systemctl restart haproxy
systemctl restart keepalived

Visit IP_MASTER:8080/stats or IP_SLAVE:8080/stats — if you see stats like in the image, HAProxy is working (2 Slave nodes down - 1 Master node Up):

HAProxy statistics page showing master and slave node status

To test the VIP, you can use the command — seeing connected means success

telnet VIP 6379

Wrapping up

This is the result of nearly a week of my own research, so there will certainly still be gaps or mistakes. Hope this post helps you out a little in your work — if you have any questions, comment below. To support me, feel free to Follow or Vote Up. See you in the next post.

If you're running into technical challenges or need help with systems, DevOps tools, I'm confident I can help. Get in touch at hoangviet.io.vn

Have thoughts on this?

I'd love to hear your perspective. Send me a message.

Get in touch