Call bind(2) before connect(2) if exists "bind ADDR" in redis.conf #1155

Closed
wants to merge 1 commit into
from

3 participants

@hirose31

Redis master recognizes slave's IP address by getpeername(2) so that address becomes an address assigned slave's eth0 even if IP aliased (eth0:1) in slave linux box and bind <IP address assigned eth0:1) in redis.conf.

This is not a promblem in simple master/slave replication except that redis-clit -h MASTER info | grep slave shows wrong slave's IP address.

Now I introduced Redis Sentinel. Sentinel gets slaves address from result of info command to master, so sentinel recognizes not slave's eth0:1 but slave's eth0 as slave's IP address.

Sentinel's health check to slave will fail because slave only listen eth0:1. If redis master crashed, sentinel cannot failover because there is no healthy slave.

To fix it, slave calls bind(2) before connect(2) to master if there is bind <address> in redis.conf and that address is not local address (127.0.0.0/8).

Could you give me any advice?

Redis master:
  IP address:
    eth0:   10.0.0.100

Redis slave:
  IP address:
    eth0:   10.0.0.200
    eth0:1: 10.0.0.201
  redis.conf:
    bind 10.0.0.201

Redis sentinel:
  IP address:
    eth0:   10.0.0.50
  sentinel.conf:
    sentinel monitor mymaster 10.0.0.100 6379 1

$ redis-cli -h 10.0.0.201 slaveof 10.0.0.100 6379

$ redis-cli -h 10.0.0.100 info | grep slave
slave0:10.0.0.200,6379,online  # not 10.0.0.201

$ redis-cli -h 10.0.0.50 sentinel slaves mymaster | grep -A1 ip
ip
10.0.0.200  # not 10.0.0.201

@hirose31 hirose31 Call bind(2) before connect(2) if exists "bind ADDR" in redis.conf
Redis master recognizes slave's IP address by getpeername(2) so that address becomes an address assigned slave's eth0 even if IP aliased (eth0:1) in slave linux box and ```bind <IP address assigned eth0:1)``` in redis.conf.

This is not a promblem in simple master/slave replication except that ```redis-clit -h MASTER info | grep slave``` shows wrong slave's IP address.

Now I introduced Redis Sentinel. Sentinel gets slaves address from result of ```info``` command to master, so sentinel recognizes not slave's eth0:1 but slave's eth0 as slave's IP address.

Sentinel's health check to slave will fail because salve only listen eth0:1. If redis master crashed, sentinel cannot failover because there is no healthy slave.

To fix it, slave calls bind(2) before connect(2) to master if there is ```bind <address>``` in redis.conf and that address is not local address (127.0.0.0/8).
d6b4698
@hirose31

@antirez
I think this issue is a critical problem when running some redis-servers on same port(6379) on same server.
What do you think about?

@clan

+1

This is very helpful. In out case, we running redis as slave on a pc, the master is a remote server which connected by vpn. For redundancy reason, there are multiple vpn connection in use, the route is decided by route policy. Then, the problem comes, if the active vpn is broken, redis will have to reconnect to the master since the address used to connect master will change. Before redis 2.8, this mean a full data re-transfer. If we can bind the client on a fixed local address, from the TCP's side, redis connection will be transparent to the vpn things. Thanks.

@mattsta

This has been fixed elsewhere in #2110

@mattsta mattsta closed this Feb 12, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment