Redis Cluster 高可用集群(Docker 实现)

本文使用Docker部署实现于同一台服务器,Redis 版本 5.0.3

单机存在的问题
  • 机器故障:导致Redis失效
  • 容量瓶颈:容量不能水平扩展
  • OPS( operation per second 每秒处理指令数):一台机器的网络带宽是有限的,如果有多台机器,可以有效解决QOS
Redis Cluster

Redis 集群是一个可以在多个 Redis 节点之间进行数据共享的设施installation。
Redis 集群通过分区partition来提供一定程度的可用性availability: 即使集群中有一部分节点失效或者无法进行通讯, 集群也可以继续处理命令请求。
Redis集群提供了以下好处:

  • 将数据自动切分 split 到多个节点的能力
  • 当集群中的一部分节点失效或者无法进行通讯时, 仍然可以继续处理命令请求的能力

Redis 集群特点:

  • 一个master可以有多个slave
  • 一个slave只能有一个master
  • 数据流向是单向的,master到slave
Redis 集群分区

参考:浅谈Redis Cluster

Redis 集群方案
哨兵模式:

  在redis3.0以前的版本要实现集群一般是借助哨兵sentinel工具来监控master节点的状态,如果master节点异常,则会做主从切换,将某一台slave作为master,哨兵的配置略微复杂,并且性能和高可用性等各方面表现一般,特别是在主从切换的瞬间存在访问瞬断的情况,而且哨兵模式只有一个主节点对外提供服务,没法支持很高的并发,且单个主节点内存也不宜设置得过大,否则会导致持久化文件过大,影响数据恢复或主从同步的效率。
在这里插入图片描述

高可用集群模式(推荐):

  redis集群是一个由多个主从节点群组成的分布式服务器群,它具有复制、高可用和分片特性。Redis集群不需要sentinel哨兵也能完成节点移除和故障转移的功能。需要将每个节点设置成集群模式,这种集群模式没有中心节点,可水平扩展,据官方文档称可以线性扩展到上万个节点(官方推荐不超过1000个节点)。redis集群的性能和高可用性均优于之前版本的哨兵模式,且集群配置非常简单。
在这里插入图片描述

Redis 高可用集群快速搭建

  redis 集群需要至少三个节点(因为领导者选举需要至少一半加1个节点,奇数个节点可以在满足该条件的基础上节省一个节点),这里我们搭建三个主节点,每个主节点下面在提供一个从节点,共6个 redis 节点(三主三从)。
tip:这里我们使用 docker 搭建在同一台服务器上,实际使用时肯定是不同的服务器,不然没有意义(Redis 版本 5.0.3)。

单机搭建测试

(为了测试是否可以使用Docker 来 搭建 Redis,可以跳过)
由 docker 仓库中拉取相应的 Redis 镜像

docker pull redis:5.0.3

创建文件夹
/usr/local/redis/conf
/usr/local/redis/data
conf 存放配置文件目录,data 存放映射数据目录

修改 redis 配置文件,设置密码(获取的linux下安装后的配置文件)。

requirepass 123456

编写 docker-compose-redis.yaml [数据映射、配置文件映射] 启动镜像:

version: "3.4"
services:
  redis:
    image: redis:5.0.3
    container_name: redis5-m1
    command: redis-server /etc/redis/redis.conf
    ports:
      - "6379:6379"
    volumes:
      - ./data:/data
      - ./conf/redis.conf:/etc/redis/redis.conf

docker-compose 命令启动

docker-compose -f docker-compose-redis.yaml up -d

启动后,测试是否可以正常访问。

集群搭建
  1. 创建对应的文件夹
    在 /usr/local/redis-cluster 下创建6个文件夹 6388 6389 6378 6379 6368 6369,每个文件夹下都创建 conf、data 目录。
  2. 编辑配置文件

端口、密码、集群密码、节点信息文件配置(按需修改)
(1)绑定端口,port 63xx (对应文件夹名称)
(2)绑定IP,bind 192.168.2.128 or 0.0.0.0
(3)指定数据存放路径,dir /usr/local/redis-cluster/7031
(4)启动集群模式,cluster-enabled yes
(5)指定集群节点配置文件,cluster-config-file nodes-7031.conf
(6)后台启动,daemonize yes
(7)指定集群节点超时时间,cluster-node-timeout 5000
(8)指定持久化方式,appendonly yes # 这是AOF 持久化,按需要选择是否开启

前5项建议修改,63xx 最好指定为文件夹名称,将63xx的redis.conf改完后再拷贝到剩下的5个目录中,然后只要全局替换redis.conf中的 port 为相应的节点即可。
注意,如果是docker运行不要设置后台运行( daemonize ),否则运行后直接退出,因为没有前台线程。且无需指定数据存放路径,通过文件映射出来即可。

  1. 启动这6个容器
    使用 docker-compose 一键启动:
    x-xxx 指定了全局变量,后面对应的 xxx 引用
    需要设置:network_mode: host (参考后面解释)
version: "3.4"

x-image:
  &default-image
  redis:5.0.3
x-restart:
  &default-restart
  always
x-command:
  &default-command
  redis-server /etc/redis/redis.conf      
x-netmode:
  &default-netmode
  host

services:
  redis1:
    image: *default-image
    restart: *default-restart
    container_name: redis5-m1
    command: *default-command
    volumes:
      - ./6368/data:/data
      - ./6368/conf/redis.conf:/etc/redis/redis.conf
    network_mode: *default-netmode
  
  redis2:
    image: *default-image
    restart: *default-restart
    container_name: redis5-m2
    command: *default-command
    volumes:
      - ./6378/data:/data
      - ./6378/conf/redis.conf:/etc/redis/redis.conf
    network_mode: *default-netmode
  
  redis3:
    image: *default-image
    restart: *default-restart
    container_name: redis5-m3
    command: *default-command
    volumes:
      - ./6388/data:/data
      - ./6388/conf/redis.conf:/etc/redis/redis.conf
    network_mode: *default-netmode

  redis4:
    image: *default-image
    restart: *default-restart
    container_name: redis5-s1
    command: *default-command
    volumes:
      - ./6369/data:/data
      - ./6369/conf/redis.conf:/etc/redis/redis.conf
    network_mode: *default-netmode

  redis5:
    image: *default-image
    restart: *default-restart
    container_name: redis5-s2
    command: *default-command
    volumes:
      - ./6379/data:/data
      - ./6379/conf/redis.conf:/etc/redis/redis.conf
    network_mode: *default-netmode   
    
  redis6:
    image: *default-image
    restart: *default-restart
    container_name: redis5-s3
    command: *default-command
    volumes:
      - ./6389/data:/data
      - ./6389/conf/redis.conf:/etc/redis/redis.conf
    network_mode: *default-netmode   

启动命令:

docker-compose -f  docker-compose-redis.yaml up -d

查看启动的服务:
在这里插入图片描述
4. 用redis-cli创建整个redis集群
(redis5以前的版本集群是依靠ruby脚本redis-trib.rb实现)
可以下载一个redis-cli镜像: goodsmileduck/redis-cli:v5.0.3

docker run --rm -it goodsmileduck/redis-cli:v5.0.3 redis-cli -a 123456 --cluster-replicas 1 --cluster create 192.168.6.181:6369 192.168.6.181:6379 192.168.6.181:6389 192.168.6.181:6368 192.168.6.181:6378 192.168.6.181:6388

# -a 表示连接密码
# --cluster-replicas 1 表示 一主一从
# --cluster create 后面表示需要集群的redis主机和端口

在这里插入图片描述
出现的问题1:
  一直显示等待加入 (Waiting for the cluster to join…
猜测原因:
  redis集群不仅需要开通redis客户端连接的端口,而且需要开通集群总线端口,集群总线端口为redis客户端连接的端口 + 10000。如redis端口为7001,则集群总线端口为17001。
解决方法:
  端口映射 6378:6379, 16378:16379
结果:
  无效
实际原因:
  当前Cluster尚不支持NATted环境,在一般环境中IP地址或者port会重新映射(remapped)。Docker使用了一种称为“port mapping”技术:在Docker容器内运行的程序使用的端口,将以另一个端口的方式暴露出去(Docket的宿主环境)。这可以允许一个Server(物理环境)上允许多个Docker容器,而且每个容器内的程序可以使用相同的端口。为了让Redis Cluster与Docker机制兼容,Docker需要使用“host networking mode”,具体信息请参考Dorcker文档
真正解决:
  网络模式改成host,docker run 的方式加上–net host,docker-compose方式加上network_mode: host。

出现的问题2:
  提示节点不为空

Node 192.168.6.181:6369 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0

原因:
  该节点下面存在数据,新增的集群下面不能存有数据
解决方法:
1).将需要新增的节点下 aof、rdb 等本地备份文件删除;
2).同时将新Node的集群配置文件删除,即:删除 redis.conf 里面 cluster-config-file 所在的文件;
3).再次添加新节点如果还是报错,则登录新Node,对数据库进行清除

# 登录 redis-cli
./redis-cli–h x –p
# 清空当前数据库
172.168.63.201:7001>  flushdb
  1. 连接任意一个客户端,设置数据
# 连接 181:6368 客户端
docker run --rm -it goodsmileduck/redis-cli:v5.0.3 redis-cli -c -h 192.168.6.181 -p 6368 -a 123456

注意原本是 6368,然后变成了 6369 (解释见后文)
在这里插入图片描述
RedisDesktopManager 查看:
在这里插入图片描述
cluster info 查看集群信息:
在这里插入图片描述
cluster nodes 查看节点信息(0-5460,5461-10922,10923-16383 表示各哈希槽区间):
在这里插入图片描述
6. 高可用测试
  我们关闭一个主节点容器,重新调用查询命令,提示一个失去连接,且其对应的从节点被投票选举为新的主节点,之前的主节点被更换为从节点(发现主从地址未改变,因为当客户端试图连接失效的主服务器时, 集群会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器)
在这里插入图片描述
重新启动该节点,再次调用查询命令,发现其已成功连接到了集群中,恢复原样
在这里插入图片描述
至此,Redis 集群搭建完毕。

Redis 集群原理

  redis cluster采用无中心结构,节点间使用gossip协议进行通信。每个节点保存数据和所有节点和槽的映射关系。其架构图如下:
在这里插入图片描述

  1. 所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。
  2. 节点的fail是通过集群中超过半数的节点检测失效时才生效。
  3. 客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。
  4. redis-cluster把所有的物理节点映射到 [0-16383] slot上,cluster 负责维护node<->slot<->value
Moved 异常

  从上图可以看出,客户端是采用直连的方式来连接redis客户端。那么redis客户端是如何知道要提交到节点呢?
  实际上,客户端可以将数据提交到任意一个redis cluster节点上,如果存储该数据的槽不在这个节点上,则返回给客户端moved异常,客户端通过moved异常,永久的将请求转移到目标节点,如下图所示。
在这里插入图片描述
首先来看下redis cluster的节点信息,执行命令redis-cli cluster nodes:
在这里插入图片描述
看到各虚拟槽分配范围 [0-5460]、[5461-10922]、[10923-16383],接下来演示该异常:
在这里插入图片描述
首先 cluster keyslot a,查看以 a 为key 的槽位在 15495上,即 6389 上,然后我们此时在 6368上设置 key - value,发现被重定向到了 6389 上。

参考:

如何用docker部署redis cluster:https://www.cnblogs.com/chenchuxin/p/8404699.html
Redis cluster集群:原理及搭建:https://blog.csdn.net/truelove12358/article/details/79612954
Redis3集群的安装、配置、高可用:https://blog.csdn.net/qq_27384769/article/details/80662597
浅谈Redis Cluster:https://blog.csdn.net/qq2430/article/details/80716313
redis主从复制原理和介绍:https://blog.csdn.net/fst438060684/article/details/80958375
Redis集群 - 配置最简单的Redis主从读写分离:https://blog.csdn.net/seven_2016/article/details/81952246
Redis 5 之后版本的高可用集群搭建:https://blog.csdn.net/qq_34002221/article/details/85011041

  • 5
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值