使用docker搭建redis集群有两种,一种是单机多个docker容器,一种是多个机器的集群
每个Redis集群中的节点都需要打开两个TCP连接。一个连接用于正常的给Client提供服务,比如6379,还有一个额外的端口(通过在这个端口号上加10000)作为数据端口,比如16379。第二个端口(本例中就是16379)用于集群总线,这是一个用二进制协议的点对点通信信道。这个集群总线(Cluster bus)用于节点的失败侦测、配置更新、故障转移授权,等等。客户端从来都不应该尝试和这些集群总线端口通信,它们只应该和正常的Redis命令端口进行通信。注意,确保在你的防火墙中开放着两个端口,否则,Redis集群节点之间将无法通信。命令端口和集群总线端口的偏移量总是10000。
Redis集群不同一致性哈希,它用一种不同的分片形式,在这种形式中,每个key都是一个概念性(hash slot)的一部分。Redis集群中的每个节点负责一部分hash slots,并允许添加和删除集群节点。比如,如果你想增加一个新的节点D,那么久需要从A、B、C节点上删除一些hash slot给到D。同样地,如果你想从集群中删除节点A,那么会将A上面的hash slots移动到B和C,当节点A上是空的时候就可以将其从集群中完全删除。因为将hash slots从一个节点移动到另一个节点并不需要停止其它的操作,添加、删除节点以及更改节点所维护的hash slots的百分比都不需要任何停机时间。也就是说,移动hash slots是并行的,移动hash slots不会影响其它操作。
为了保持可用,Redis集群用一个master-slave模式,这样的话每个hash slot就有1到N个副本。而redis-cluster规定,至少需要3个master和3个slave,即3个master-slave对。当我们给每个master节点添加一个slave节点以后,我们的集群最终会变成由A、B、C三个master节点和A1、B1、C1三个slave节点组成,这个时候如果B失败了,系统仍然可用。节点B1是B的副本,如果B失败了,集群会将B1提升为新的master,从而继续提供服务。然而,如果B和B1同时失败了,那么整个集群将不可用。
Redis集群不能保证强一致性。换句话说,Redis集群可能会丢失一些写操作,原因是因为它用异步复制.
本段内容复制于docker redis 集群(cluster)搭建
先准备一台安装docker的机器,本人准备的是ubuntu的机器 没有安装ruby
docker network create redis-cluster-net
mkdir -p 6371/data && mkdir -p 6372/data
mkdir -p 6373/data && mkdir -p 6374/data
mkdir -p 6375/data && mkdir -p 6376/data
# bind 127.0.0.1
protected-mode no
port ${PORT} #6371 -> 6376
daemonize no
dir /data/redis
appendonly yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 15000
sudo apt-get install ruby
sudo apt-get install gem
sudo gem install redis
wget http://download.redis.io/releases/redis-4.0.1.tar.gz
tar -xvf redis-4.0.1.tar.gz
cd redis-4.0.1
make
然后 redis-4.0.1目录下面的src中的 redis_trib.rb 就可以使用了
docker run -d -it -p 6371:6371 -p 16371:16371 \
-v /mnt/data/redis/6371/redis.conf:/data/redis.conf -v /mnt/data/redis/6371/data/:/data/redis/ \
--restart always --name redis-6371 --net redis-cluster-net redis:4.0.1 redis-server /data/redis.conf;
docker run -d -it -p 6372:6372 -p 16372:16372 \
-v /mnt/data/redis/6372/redis.conf:/data/redis.conf -v /mnt/data/redis/6372/data/:/data/redis/ \
--restart always --name redis-6372 --net redis-cluster-net redis:4.0.1 redis-server /data/redis.conf;
docker run -d -it -p 6373:6373 -p 16373:16373 \
-v /mnt/data/redis/6373/redis.conf:/data/redis.conf -v /mnt/data/redis/6373/data/:/data/redis/ \
--restart always --name redis-6373 --net redis-cluster-net redis:4.0.1 redis-server /data/redis.conf;
docker run -d -it -p 6374:6374 -p 16374:16374 \
-v /mnt/data/redis/6374/redis.conf:/data/redis.conf -v /mnt/data/redis/6374/data/:/data/redis/ \
--restart always --name redis-6374 --net redis-cluster-net redis:4.0.1 redis-server /data/redis.conf;
docker run -d -it -p 6375:6375 -p 16375:16375 \
-v /mnt/data/redis/6375/redis.conf:/data/redis.conf -v /mnt/data/redis/6375/data/:/data/redis/ \
--restart always --name redis-6375 --net redis-cluster-net redis:4.0.1 redis-server /data/redis.conf;
docker run -d -it -p 6376:6376 -p 16376:16376 \
-v /mnt/data/redis/6376/redis.conf:/data/redis.conf -v /mnt/data/redis/6376/data/:/data/redis/ \
--restart always --name redis-6376 --net redis-cluster-net redis:4.0.1 redis-server /data/redis.conf;
matches=""
for port in `seq 6371 6376`; do
matches=$matches$(docker inspect --format '{{(index .NetworkSettings.Networks "redis-cluster-net").IPAddress}}' "redis-${port}"):${port}" ";
done
echo $matches
redis-4.0.1/src/redis-trib.rb create create --replicas 1 $matches
然后会进入集群的配置行,只要敲击yes就能自动完成集群的配置.
redis-cli -p 6371
127.0.0.1:6371> set a aaa
(error) MOVED 15495 172.18.0.4:6373
127.0.0.1:6371> get a
(error) MOVED 15495 172.18.0.4:6373
127.0.0.1:6371>
redis-cli -p 6373
127.0.0.1:6373> get a
(nil)
可见,并没有将数据set到redis集群中
然后在172.18.0.2的机器上
redis-cli -c -p 6371
172.18.0.2:6371> set b bbbb
OK
172.18.0.4:6373> get b
-> Redirected to slot [3300] located at 172.18.0.2:6371
"bbbb"
172.18.0.2:6371>
所以在使用redis-cli的使用,要是有-c才能访问到集群中的数据.
redis-cli -c -h 172.18.0.2 -p 6371
172.18.0.2:6371>get a
-> Redirected to slot [15495] located at 172.18.0.4:6373
一段时间等待后
Could not connect to Redis at 172.18.0.4:6373: Connection timed out
断开了链接...
所以 单机的这种建立network只能在这个网络上的能访问,在其他的机器上就不能访问了.