Description
We use several bare metal nodes to host a redis cluster.
Naturally, not all nodes in the redis cluster use the same port. In order to discovery the cluster topology, at first we used
// hardcode or use a external system to obtain several "seed" node
// I understand not all of them are needed here since there will be a internal discovery later to find all the nodes.
client := redis.NewClusterClient(&redis.ClusterOptions{
Addrs: []string{"host1:port1","host1:port2","host2:port1","host2:port2"},
})
We definitely don't want to hardcode. Using an external system is essentially also hardcode since once the client is created the node information is fixed.
A solution I can come up with would be to pass a DNS name into the client and let the client do a DNS SRV resolve every time it needs, which completely eliminate the hardcode. However this functionality is not supported.
Later I tried to implement it as a custom net.Dialer like
func dial(ctx context.Context, network, addr string) (net.Conn, error) {
nd := &net.Dialer{
Timeout: 5 * time.Second, // from github.com/redis/go-redis/v9.NewDialer
KeepAlive: 5 * time.Minute, // from github.com/redis/go-redis/v9.NewDialer
}
host, port, err := mypkg.ResolveSRV(addr)
if err != nil {
return nil, err
}
addr = net.JoinHostPort(host, port)
return nd.DialContext(ctx, network, addr)
}
and the use the dialer like
client := redis.NewClusterClient(&redis.ClusterOptions{
Addrs: []string{"some-reds.internal"},
Dialer: dial,
})
However, the mypkg.ResolveSRV
is not straightforward to implement but needs an understanding of the internal discovery process implementation( I can explain the problem in detail if needed)
So, I wonder if we can implement DNS SRV inside this library, or maybe there are other solutions to avoid hardcode