Fix sentinel function that compares hostnames (if failed resolve) (#11419)

Funcion sentinelAddrEqualsHostname() of sentinel makes DNS resolve
and based on it determines if two IP addresses are equal. Now, If the
DNS resolve command fails, the function simply returns 0, even if the
hostnames are identical.

This might become an issue in case of failover such that sentinel might
receives from Redis instance, response to regular INFO query it sent,
and wrongly decide that the instance is pointing to is different leader
than the one recorded because of this function, yet hostnames are
identical. In turn sentinel disconnects the connection between sentinel
and valid slave which leads to -failover-abort-no-good-slave.
See issue #11241.

I managed to reproduce only part of the flow in which the function
return wrong result and trigger +fix-slave-config.

The fix is even if the function failed to resolve then compare based on
hostnames. That is our best effort as long as the server is unavailable
for some reason. It is fine since Redis instance cannot have multiple
hostnames for a given setup
This commit is contained in:
Moti Cohen 2022-10-23 16:00:47 +03:00 committed by GitHub
parent 20df1424a2
commit bd23b15ad7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -616,10 +616,16 @@ int sentinelAddrOrHostnameEqual(sentinelAddr *a, sentinelAddr *b) {
int sentinelAddrEqualsHostname(sentinelAddr *a, char *hostname) {
char ip[NET_IP_STR_LEN];
/* We always resolve the hostname and compare it to the address */
/* Try resolve the hostname and compare it to the address */
if (anetResolve(NULL, hostname, ip, sizeof(ip),
sentinel.resolve_hostnames ? ANET_NONE : ANET_IP_ONLY) == ANET_ERR)
return 0;
sentinel.resolve_hostnames ? ANET_NONE : ANET_IP_ONLY) == ANET_ERR) {
/* If failed resolve then compare based on hostnames. That is our best effort as
* long as the server is unavailable for some reason. It is fine since Redis
* instance cannot have multiple hostnames for a given setup */
return !strcasecmp(sentinel.resolve_hostnames ? a->hostname : a->ip, hostname);
}
/* Compare based on address */
return !strcasecmp(a->ip, ip);
}