-
Notifications
You must be signed in to change notification settings - Fork 61
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
Using Redis clustering #127
Comments
I have never tried this shard with Redis in cluster mode, and I don't know if anybody has done so, or what it would take to get it to work. |
I briefly looked at how the Ruby client does it. I think what that was doing was run the command, if it fails with this "MOVED" command, then you rescue and grab the host that contains the data and run the command against that host. So in a pseudo-code way: cluster = Redis.new(cluster: ["redis://1.2.3.4:6379", "redis://4.5.6.7:6379"])
cluster.lrange("thing", 0, -1)
# somewhere deep inside
private def make_call
run
rescue e : RedisFailed
if e.message =~ /MOVED/
host = get_host_from_error(e)
Redis.current_host = host
make_call
end
end I'm sure it's a lot more complicated than that, but that was the general idea I saw the ruby client doing. I don't think it was too bad getting it to recreate locally using https://github.com/bitnami/bitnami-docker-redis-cluster. Boot up these cluster redis in Docker locally, and then you can just run @russ might be able to provide a bit more insight and a docker-compose that worked... |
Here is the docker-compose.yml file I used to boot a cluster.
Then just a simple request for data.
My understanding is that the cluster responds with what node the data is actually on. So if I connect to the node given back, then I can fetch the data.
|
Hat tip to @jwoertink for pointing me to this issue. The way I implemented this in my own Redis shard was by creating an abstraction for clusters that automatically routes commands to the right servers based on the key name (inferred from the second element in the command array) and whether it's a read or write command. This is cleaner and more performant (and, in the case of The server that holds a given key can be derived with
The above Show script#!/usr/bin/env ruby
starting_port = 6379
masters = 3
replicas_per_master = 2
hosts = []
pids = []
(masters * (replicas_per_master + 1)).times do |i|
port = starting_port + i
cmd = "redis-server --port #{port} --cluster-enabled yes --cluster-config-file redis-#{port}.conf --appendonly yes --appendfilename redis-#{port}.aof --dbfilename redis-#{port}.rdb > redis-#{port}.log"
hosts << "127.0.0.1:#{port}"
pids << spawn(cmd)
end
# Wire up all the Redis servers to each other
puts "Wiring up servers into a cluster..."
cluster_command = "redis-cli --cluster create #{hosts.join(' ')} --cluster-replicas #{replicas_per_master} --cluster-yes"
puts cluster_command
system cluster_command
puts "Press Enter to terminate Redis cluster"
gets
pids.each do |pid|
Process.kill "TERM", pid
Process.wait pid
end |
We have Redis on AWS in cluster mode, and it's been fine while using Cable-cr. However, we just tried to use this shard directly to store some data, and ran in to some issues:
This ends up throwing an exception. Is there a way to handle this already? Or something that will have to be added in to support?
The text was updated successfully, but these errors were encountered: