阅读 1264

docker-compose搭建redis集群及可用性实践

集群搭建概述

redis一般需要6个节点才能组成完整的高可用集群,这里我们使用docker-compose来快速搭建集群。 集群搭建一般分为三个步骤:

  • 准备节点
  • 节点握手
  • 分配槽

步骤一:准备节点

从GitHub下载代码

项目GitHub地址:github.com/willcat/red…

注意

由于代码更新,在配置文件中手动设置了容器名称,所以文章和代码中的容器名有区别,比如文章中的redis-cluster_redis-cluster-6380_1,在代码和实际运行中是node-80,文章中的redis-cluster_redis-cluster-6381_1,在代码和实际运行中是node-81

开启后台服务,启动所有节点

进入redis-cluster-docker目录,执行docker-compose up -d

检查当前集群状况

随便进入一个容器比如redis-cluster_redis-cluster-6380_1[1],docker exec -it redis-cluster_redis-cluster-6380_1 redis-cli -p 6380,然后运行cluster nodes命令,整个过程如下:

$ docker exec -it redis-cluster_redis-cluster-6380_1 redis-cli -p 6380
127.0.0.1:6380> cluster nodes
3914fe7597f9ad9e9c485cf473bcaa461973baaa :6380@16380 myself,master - 0 0 0 connected

复制代码

可以看到目前各个节点还只能返回自己的信息,每个节点还不能感知到彼此。

[1] 这是docker-compose根据我们在docker-compose.yml配置的服务名称自动生成的,如果不想使用默认名称,可以在配置文件中使用container_name指定容器名称 docker exec

步骤二 节点握手

节点握手是指一批运行在集群模式下的节点通过Gossip协议彼此通信,达到感知对方的过程。

  • 在某个节点上执行cluster meet {ip} {port}命令,达到两个节点间的握手,这两个节点就组成了一个真正的彼此感知的集群,之后两个节点间会定期通过ping/pong消息进行正常的节点通信
  • 在集群中任意节点上执行cluster meet {ip} {port}命令,添加尚未加入集群的新节点
  • 所有节点全部加入之后可以看到集群中所有节点信息
127.0.0.1:6380> cluster nodes
c6db83c252a072407707917474001c70da649407 172.26.0.6:6385@16385 master - 0 1565199856348 3 connected
e356c336482f7a8a3f786674b96ac06030b0dcb4 172.26.0.3:6381@16381 master - 0 1565199855000 0 connected
dae83c485b9fb1357947944b36007c3371a750f2 172.26.0.7:6383@16383 master - 0 1565199857362 5 connected
c87aba899473356f25a919dc2d477340f5222ba4 172.26.0.2:6382@16382 master - 0 1565199855000 4 connected
5ebbd85dfbe1e4e01bae5f4954418a436453876c 172.26.0.5:6384@16384 master - 0 1565199855339 2 connected
3914fe7597f9ad9e9c485cf473bcaa461973baaa 172.26.0.4:6380@16380 myself,master - 0 1565199855000 1 connected
复制代码

补充知识:docker-compose默认组网

  • 使用docker-compose up启动容器后,这些容器都会被加入{app_name}_default网络中
  • 使用docker network ls可以查看网络列表,docker network inspect <network_name>可以查看对应网络的配置以及各个容器的ip。
  • 还可以通过docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' redis-cluster_redis-cluster-6385_1命令直接查看某个容器的ip。

步骤三 分配槽

节点建立握手之后,集群还处于下线状态,无法执行写操作。

127.0.0.1:6380> set hello world
(error) CLUSTERDOWN Hash slot not served
复制代码

查看集群信息可以看到集群是fail状态

127.0.0.1:6380> cluster info
cluster_state:fail
cluster_slots_assigned:0
cluster_slots_ok:0
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:0
cluster_current_epoch:5
cluster_my_epoch:1
cluster_stats_messages_ping_sent:718
cluster_stats_messages_pong_sent:283
cluster_stats_messages_meet_sent:8
cluster_stats_messages_sent:1009
cluster_stats_messages_ping_received:283
cluster_stats_messages_pong_received:285
cluster_stats_messages_received:568
复制代码

执行分配槽的命令

在各个节点上执行类似cluster addslots {0...5461}的命令,将0~16383个slot平均分配到所有节点上。这里我们只分配三个节点,另外三个节点分别当作前面三个节点的从节点,从而在主节点出现故障时能够自动完成故障转移。

//分配三个节点,注意,以下三个命令在登录redis-cli之后是不成功的,只能使用redis-cli -p 6380 cluster addslots {0..5461}这种模式
$ docker exec -it redis-cluster_redis-cluster-6380_1 redis-cli -p 6380 cluster addslots {0..5461}
$ docker exec -it redis-cluster_redis-cluster-6381_1 redis-cli -p 6381 cluster addslots {5462..10922}
$ docker exec -it redis-cluster_redis-cluster-6382_1 redis-cli -p 6382 cluster addslots {10923..16282}

// 将三个未分配槽的节点设置为从节点
127.0.0.1:6383> CLUSTER REPLICATE 3914fe7597f9ad9e9c485cf473bcaa461973baaa
OK

127.0.0.1:6384> CLUSTER REPLICATE e356c336482f7a8a3f786674b96ac06030b0dcb4
OK

127.0.0.1:6385> CLUSTER REPLICATE  c87aba899473356f25a919dc2d477340f5222ba4
OK
复制代码

官方集群快速搭建工具

这样3主3从的集群就搭建完成了,可以感觉到还是比较麻烦的,所以redis官方在redis3.xredis4.x提供了redis-trib.rb工具方便我们快速搭建集群,在redis5.x中更是可以直接使用redis-cli命令来直接完成集群的一键搭建,省去了redis-trib.rb依赖ruby环境的问题。在代码中,readme.md里提供了快速搭建的命令。

//官方指出: 可以使用redis5.x 的redis-cli命令模式来搭建由redis-4.x组成的集群。
redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 \
127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 \
--cluster-replicas 1
复制代码

集群使用

请求重定向

在集群中某个节点读写不属于此节点的数据会返回错误(error) MOVED 5798 172.20.0.6:6381,为了减少手动切换的环节,在开启客户端时可以添加-c参数,开启请求重定向,详细命令redis-cli -p 6380 -c,这样以后操作跨节点时会自动跳转到相应的节点

Smart客户端

大多数开发语言的Redis客户端都采用Smart客户端支持集群协议,客户端选择可以参考clients

  • Smart客户端在内容维护slot->node的映射关系,本地就可实现键到节点的查找,从而保证IO效率的最大化
  • Moved重定向负责协助Smart客户端更新slot->node的映射关系。

ASK重定向

当集群伸缩时,slot会发生迁移,这时去原来节点读写会返回(error) ASK {slot} {targetIP}:{targetPort}错误,客户端从ASK重定向异常提取出目标节点信息,发送asking命令到目标节点打开客户端连接标识,再执行键命令。如果存在则执行,不存在则返回不存在信息。

集群容错

TODO

关注下面的标签,发现更多相似文章
评论