社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  docker

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

willcat • 6 年前 • 410 次点击  
阅读 13

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

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/37282