I have built a redis cluster with 6 nodes with port from 7000-7005
by using docker with each redis using redis.conf
like this:
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
protected-mode no
In file `docker-compose.yaml’:
version: "3.9"
services:
redis-node-1:
container_name: redis-node-1
image: redis/redis-stack-server:latest
volumes:
- ./build/redis/redis.conf:/usr/local/etc/redis/redis.conf
- ./data/redis-node-1:/data
ports:
- "7000:7000"
- "17000:17000"
entrypoint: [ "redis-server", "/usr/local/etc/redis/redis.conf", --port,"7000" ]
networks:
redis_cluster_network:
ipv4_address: 173.18.0.5
redis-node-2:
container_name: redis-node-2
image: redis/redis-stack-server:latest
volumes:
- ./build/redis/redis.conf:/usr/local/etc/redis/redis.conf
- ./data/redis-node-2:/data
ports:
- "7001:7001"
- "17001:17001"
entrypoint: [ "redis-server", "/usr/local/etc/redis/redis.conf", --port,"7001" ]
networks:
redis_cluster_network:
ipv4_address: 173.18.0.6
redis-node-3:
container_name: redis-node-3
image: redis/redis-stack-server:latest
volumes:
- ./build/redis/redis.conf:/usr/local/etc/redis/redis.conf
- ./data/redis-node-3:/data
ports:
- "7002:7002"
- "17002:17002"
entrypoint: [ "redis-server", "/usr/local/etc/redis/redis.conf", --port,"7002" ]
networks:
redis_cluster_network:
ipv4_address: 173.18.0.7
redis-node-4:
container_name: redis-node-4
image: redis/redis-stack-server:latest
volumes:
- ./build/redis/redis.conf:/usr/local/etc/redis/redis.conf
- ./data/redis-node-4:/data
ports:
- "7003:7003"
- "17003:17003"
entrypoint: [ "redis-server", "/usr/local/etc/redis/redis.conf", --port,"7003" ]
depends_on:
- redis-node-1
- redis-node-2
- redis-node-3
networks:
redis_cluster_network:
ipv4_address: 173.18.0.8
redis-node-5:
container_name: redis-node-5
image: redis/redis-stack-server:latest
volumes:
- ./build/redis/redis.conf:/usr/local/etc/redis/redis.conf
- ./data/redis-node-5:/data
ports:
- "7004:7004"
- "17004:17004"
entrypoint: [ "redis-server", "/usr/local/etc/redis/redis.conf", --port,"7004" ]
depends_on:
- redis-node-1
- redis-node-2
- redis-node-3
networks:
redis_cluster_network:
ipv4_address: 173.18.0.9
redis-node-6:
container_name: redis-node-6
image: redis/redis-stack-server:latest
volumes:
- ./build/redis/redis.conf:/usr/local/etc/redis/redis.conf
- ./data/redis-node-6:/data
ports:
- "7005:7005"
- "17005:17005"
entrypoint: [ "redis-server", "/usr/local/etc/redis/redis.conf", --port,"7005" ]
depends_on:
- redis-node-1
- redis-node-2
- redis-node-3
networks:
redis_cluster_network:
ipv4_address: 173.18.0.10
redis-cluster-creator:
container_name: redis-cluster-creator
image: redis/redis-stack-server:latest
command: 'redis-cli -p 7002 --cluster create 173.18.0.5:7000 173.18.0.6:7001 173.18.0.7:7002 173.18.0.8:7003 173.18.0.9:7004 173.18.0.10:7005 --cluster-replicas 1 --cluster-yes'
depends_on:
- redis-node-1
- redis-node-2
- redis-node-3
- redis-node-4
- redis-node-5
- redis-node-6
networks:
redis_cluster_network:
ipv4_address: 173.18.0.11
networks:
redis_cluster_network:
driver: bridge
ipam:
driver: default
config:
- subnet: 173.18.0.0/16
But when I try to connect with go-redis by using:
redisClient := redis.NewClusterClient(&redis.ClusterOptions{
Addrs: cfg.RedisCache.Address,
Password: cfg.RedisCache.Password,
PoolSize: cfg.RedisCache.PoolSize,
MaxRetries: cfg.RedisCache.MaxRetries,
ReadOnly: true,
RouteRandomly: true,
})
err = redisClient.ForEachShard(ctx, func(ctx context.Context, shard *redis.Client) error {
return shard.Ping(ctx).Err()
})
if err != nil {
apiLogger.Fatal(err)
}
I always get error from one of each node like: dial tcp 173.18.0.7:7000: i/o timeout
Have I miss some configurations?
I have read go-redis guide. It tells me that I should wait to all redis node run before the app running in docker-compose. But I only use docker-compose for redis, not include my app. I’m sure that all redis nodes are completed running. And that error still happens.
2
Answers
I have also run into similar issues when trying to run it fixed IPs, so what I figured out is the following:
Here is an example of the docker-compose.yml
And here is the
main.go
:Remark: The Go program does NOT run in Docker, if you want it, some adjustments of the URLs may be needed.
There are too many moving parts. The network part for example is totally unnecessary to get this running:
I put the app in here for not for mere convenience, but as a necessity: You instructed redis to bind to
0.0.0.0
, which roughly translates toNow, here is what happens under the hood, as far as I understand it: You contact one of the cluster nodes, ask for a key (everything is behind a key in redis) and you will be redirected to the master of the shard holding said value. But the cluster does only know the internal IP of said master, in the example you have given
173.18.0.7
. However, its IP range is most likely not available on your network (those are PUBLIC IPs) let alone the host machine, unless you happen to work for or a customer of MediaCom:Hence, the most probable culprit is the rather weird network config.
You can find the docker compose as well as a small Go application for testing and an accompanying
Dockerfile
at https://github.com/mwmahlberg/redis-78155633.