Skip to content

Discovery cluster topology without hardcode #3368

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
rpstw opened this issue May 7, 2025 · 2 comments
Closed

Discovery cluster topology without hardcode #3368

rpstw opened this issue May 7, 2025 · 2 comments

Comments

@rpstw
Copy link

rpstw commented May 7, 2025

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

@ndyakov
Copy link
Member

ndyakov commented May 12, 2025

Hello @rpstw I did wrote a response, but seems i forgot to post it. I do think this is something that should be implemented in the application and not in the client. The client itself provides you a hook (the dialer) where you can resolve the address and the port. Better approach to get the cluster topology would be to use

ClusterSlots func(context.Context) ([]ClusterSlot, error)

@ndyakov ndyakov closed this as not planned Won't fix, can't repro, duplicate, stale May 12, 2025
@rpstw
Copy link
Author

rpstw commented May 12, 2025

ClusterSlots is exactly what we need and thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants