一、什么是redis集群
Redis集群是一个提供在多个Redis节点之间共享数据的程序集。它并不像Redis主从复制模式那样只提供一个master节点提供写服务,而是会提供多个master节点提供写服务,每个master节点中存储的数据都不一样,这些数据通过数据分片的方式被自动分割到不同的master节点上。
如上图 ,3 个 Redis 作为一个集群,一共有3个master节点,每个master节点会分得一部分的哈希槽 , 但是,当某一个 Redis 服务节点突然间出现故障了么办呢?为了使得整个集群变得高可用,我们给每个 master 节点下面至少增加一个slave 节点,当某个master 节点故障,则会自动使用slave 升级为master节点。那么集群如何知道某个节点故障了呢?这里就要说到他直接的通讯方式【每个节点都使用tcp协议相互通讯交流,当有某个master 出现故障是,所有节点都会知道这个出现故障的master ,这是 集群会自动把故障下面的slave升级为master节点】,当在每个master 节点下增加 slave 节点,这样,整个集群就会有 6个节点。
如上图,增加了主从的 slave 节点,整个集群就变成了 6个节点。这6个节点是如何通讯,并且是如何存储数据的呢?
二、集群哈希槽
Redis集群中引入了哈希槽的概念,Redis集群有一共有16384个哈希槽【0,1,2,……,16382,16383】,进行set操作时,每个key会通过CRC16校验后再对16384取模来决定放置在哪个槽,搭建Redis集群时会先给集群中每个master节点分配一部分哈希槽。比如当前集群有3个master节点,master1节点包含0~5500号哈希槽,master2节点包含5501~11000号哈希槽,master3节点包含11001~16383号哈希槽,当我们执行“set key value”时,假如 CRC16(key) % 16384 = 777,那么这个key就会被分配到master6381节点上,如下图
使用哈希槽的方式,一共16384个槽位,当需要增加一个新的master节点时,只需要把对应槽位的数据移动到对应的槽位上即可。
三、集群节点的通讯方式
Redis集群中,节点之间通过建立TCP连接,使用gossip协议来传播集群的信息。什么是gossip协议呢?通俗一点的就是一群大妈,大家围起来在树头下聊天,把自己的八卦说给其他大妈听。在集群上,master1 分别使用 tcp 连接把自身的情况告诉 master2、master3 、slave1 、slave2、slave3 这5个节点;相对的 这5个节点也对应建立 tcp 链接,把自身的情况告知其他的节点。
四、集群的搭建
Redis 集群最少需要 3个 master节点,为了高可用 给每个master 节点下面配置一个或多个 slave 节点,在这里,我们使用 3个 master + 3个 slave 来部署集群。
环境搭建:Centos 7 + docker
查看服务器IP
# ip addr
结果输出:
ens33: 里面的 inet 为我们服务器的 IP 地址
docker0:里面的inet 为我们的docker IP 地址
服务器IP: 192.168.23.131
docker 的IP : 172.17.0.1
请基础上面两个IP
---------------------------------------------------
不会用docker 的请自行研究
安装 redis 镜像
// 安装最新的 redis 镜像
docker pull redis:latest
使用 docker images [iamge_name] 命令可以查看到redis 的镜像
预设对应的端口
由于我这个是在同一个服务器下进行操作,因此预设下面6个端口,在创建 docker 的 redis 容器时,把容器中的 6379 端口分别映射到主机的6个端口上。
现在安装 6 个redis 容器,6个容器分别对应 主机的端口:
6381 | 6382 | 6383 | 6384 | 6385 | 6386 |
创建对应端口的配置文件
由于这里是docker 在同一个服务器下,因此需要在主机服务器先创建好配置文件,然后在创建redis 容器时,对配置文件进行挂载。
1、创建存放集群配置的文件夹 redis_cluster
mkdir redis-cluster
输出
2、创建一个redis配置模板文件【redis-conf.tmpl】
下面为部分配置,详细的配置请看
redis配置文件详解_流水武qin的博客-CSDN博客一文解析redis配置文件_redis配置文件详解https://blog.csdn.net/qq_44749491/article/details/128091887
port ${PORT}
masterauth 123456
requirepass 123456
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.17.0.1
cluster-announce-port ${PORT}
cluster-announce-bus-port 1${PORT}
appendonly yes
配置描述说明
port | redis 端口号 |
masterauth | 对于主从结构的redis集群,当主redis设置了连接密码时,需要在从redis上设置此密码。 |
requirepass | redis实例自身的连接密码,当客户端请求连接当前Redis服务器时,需要使用的密码 |
cluster-enabled | 启动集群模式 |
cluster-config-file nodes.conf | 集群节点信息文件 |
cluster-node-timeout 5000 | redis节点宕机被发现的时间 |
cluster-announce-ip | (集群节点的汇报ip,防止nat,预先填写为网关ip后续需要手动修改配置文件) ,单机直接使用 ifconfig 如下, 直接使用docker 的ip 172.17.0.1 |
cluster-announce-port | 集群节点的汇报port,防止nat |
cluster-announce-bus-port | 集群节点的汇报bus-port,防止nat |
appendonly yes | 开启aof |
创建模板后
创建一下文件,并且根据上诉模板 替换对应的${POST} 端口号
请看 每个端口号文件夹对应的redis.conf ,下面是我的端口6381 下面的 redis.conf 文件的内容,跟模板一致,只是端口号替换成了对应的数字:
快速创建文件的命令
# 直接运行
for port in `seq 6381 6386`; do
mkdir -p ${port}/conf &&
mkdir -p ${port}/data &&
PORT=${port} envsubst < ./redis-conf.tmpl > ./${port}/conf/redis.conf
done
3、创建对应端口号的容器
根据上面的端口号和对应的文件配置,创建对应的容器
for port in `seq 6381 6386`; do
docker run -d --net=host -v /home/yel/redis-cluster/${port}/conf/redis.conf:/etc/redis/redis.conf -v /home/yel/redis-cluster/${port}/data:/data --restart always --name=redis-${port} redis redis-server /etc/redis/redis.conf;
done
运行结果:
可以看到上图,6个容器均创建成功,并且已经全部正在运行中;如果某个容器出现问题或者状态不对,请使用docker logs 容器ID 进行查看对应容器的日志。
docker logs 使用说明_Yel_Liang的博客-CSDN博客docker logs 使用说明https://blog.csdn.net/Yel_Liang/article/details/132087291
运行成功后,我们可以尝试一下链接上面的redis
这台是我本机的redis 管理工具,下面链接一下,看看是否链接成功
从上图可见,本地是可以访问虚拟机上面docker 容器的 6381 端口 下的redis 的,如果您不能访问,则需要开放防火墙端口,我这里提前关闭了防火墙。
当我们在工具上添加数据时,发现无法数据
报错 CLUSTERDOWN Hash slot not served
在上面的操作中,我们可以看到,我们只是把容器给创建并且启动起来了,而且对应的redis 配置时已经开启了集群模式 【cluster-enabled yes】,虽然把redis 启动起来了,但是还没有把 这 6个 redis 服务进行一个链接
4、创建集群
随便进入一个redis 容器内部
docker exec -it redis-6381 /bin/bash
执行 创建集群 命令
// 创建集群
redis-cli -a 123456 --cluster create 172.17.0.1:6381 172.17.0.1:6382 172.17.0.1:6383 172.17.0.1:6384 172.17.0.1:6385 172.17.0.1:6386 --cluster-replicas 1
能看到上图输出,即创建集群成功,现在我们查看一下这6个redis 服务在整个集群中担任什么角色。
5、查看集群状态
进入容器
// 随便进入一个容器内部
docker exec -it redis-6381 /bin/bash
查看集群主从详情
// 查看集群主从详情
redis-cli -a 123456 -c -p 6381 cluster nodes
在上面可以看到哪个服务器是主节点,哪个是从节点,并且能看到主节点分配的哈希槽的范围是多少,详细看下图:
通过上图,可以看出集群内的节点情况。
6、在redis容器内进行操作
进入容器内
// 随便进入一个容器内部
docker exec -it redis-6381 /bin/bash
进入redis 内部
redis-cli -a 123456 -c -h 192.168.23.131 -p 6381
参数此说明:
- -a password :登录密码
- -c : 集群模式,如果不写,进去之后,哈希槽值不在当前redis 服务内,则会抛出 MOVED 错误。
- -h : 服务器地址 , 这个地址可以是 192.168.23.131 / 172.17.0.1 ,因为当时在创建容器的时候,使用了 --net=host ,详细请看docker --net详解_Docker网络通信_weixin_34608222的博客-CSDN博客Docker:网络模式详解 - Gringer - 博客园www.cnblogs.com安装Docker时,它会自动创建三个网络,bridge(创建容器默认连接到此网络)、 none 、hostdocker run创建Docker容器时,可以用 --net 选项指定容器的网络模式 :host模式:使用 --net=host 指定。none模式:使用 --net=none 指定。bridge模..._docker nethttps://blog.csdn.net/weixin_34608222/article/details/113537311
- -p:端口
操作结果:
从上图可以看出,我们已经能进入redis 里面了,下面尝试写入
当我们输入 【set yel 感谢看到这里 】 后,提示
Redirected to slot [8044] located at 172.17.0.1:6382
因为 在输入的时候 CRC16(yel) % 16384 = 8044 ,哈希槽为 8044 ,在上面第5点【5、查看集群状态】时,可以看到 8044 哈希槽值 在 6382 这个master节点上,因此redis 告诉我们,8044 这个哈希槽在 6382 ,我帮你定向到 这个 6382 这个master节点,然后进行写入。
在主机上链接一下 6382 这个redis 节点,查看里面的数据
从上图可以看到,刚开始写入的 【set yel 感谢看到这里 】 已经被写进入了,现在我们尝试在 redis 管理器进行写入,看又是什么效果。
从上图,他告诉我们[set 2323 2323 ] 这个 哈希槽在 14515 ,应该移动到 6383 的 master 节点(node)上写入,因此在本地使用redis 管理工具链接时非集群的方式,因此抛出。
MOVED 14515 172.17.0.1:6383
7、当一个master故障后
在【6、在redis容器内进行操作】 ,我们在 6382 master节点上写入了一个 键值 为 yel 的值 ,这时 当 6382 master节点突然间故障掉,后面redis 容器会变为什么状态呢?
a、在docker 里面,停掉 6382 这个容器。
b、查看redis 集群的主从信息
根据上面的信息,得出下面的图。
我们可以看到,当redis 集群的某个主节点(master)出现故障后,主节点(master)下面的从节点(slave)被集群提升为了 主节点 ,现在我们进入 6384 节点,看一下节点 6384 里面的是否有 键值 yel
在上图我们看到, 原本 键值 yel 是在 6382 主节点上,但是 6382节点故障后,6384节点竟然也存在 键值 yel 。由于 6382 与 6384 是主从结构,在 6382 中写入的数据,会同步到 6384 里面,因此在6382 节点故障,并不会影响到 redis 整个集群的工作。但是现在我们如果把 6382 给重新修复开启起来,会有怎样的效果呢?
8、修复故障master后
上图,先通过 docker start redis-6382 启动了 redis-6382 容器,
通过docker ps -a 查看容器状态 , 使用 docker exec 进入 容器内部,查看一下 键值 yel 在不在,根据上图,可以看到,这个 yel键值 还在 6384 中,查看容器的状态,看到 6382 变成了 6384 的 从节点,当把 6384 故障掉后,如下如
从上图可以看到 , 节点6384 故障掉之后,从节点 6382 代替了 6384 变成了主节点,然后进去查看 键值 yel , 发现 yel 键值 在 6382 节点中 。
9、集群故障一个主节点和这个主节点下的从节点
从上图,看到 6382 和 6384 两个节点故障了,只剩下2个主节点和2个从节点,看哈希槽值的分配,可以看到 5461~10922 这部分的槽值故障掉了 , 现在查看集群中 键值 yel 还在不在集群中。
从上图可以发现,整个集群宕机了,这时,整个集群变为不可用的状态。想要整个集群启用,重新开启 容器 6382 或 6384 即可。开启之后,查看 键值 yel 还在不在集群中。
在 6382 中还是存在键值 yel, 这是为什么呢?因为在我们配置集群的时候,配置参数 为 aof 持久化机制 [appendonly yes] 。
五、如何增加一个主节点
1、准备环节
新增主节点端口 6391
2、创建配置文件
mkdir -p 6391/conf &&
mkdir -p 6391/data &&
PORT=6391 envsubst < ./redis-conf.tmpl > ./6391/conf/redis.conf
运行结果:
3、创建redis容器
docker run -d --net=host -v /home/yel/redis-cluster/6391/conf/redis.conf:/etc/redis/redis.conf -v /home/yel/redis-cluster/6391/data:/data --restart always --name=redis-6391 redis redis-server /etc/redis/redis.conf;
运行结果
从上图可以知道。新创建了一个容器 redis-6391,运行成功。
4、给redis 集群增加master节点
a、进入redis 内部
docker exec -it redis-6391 /bin/bash
b、给集群增加master节点
redis-cli -a 123456 --cluster add-node 192.168.23.131:6391 192.168.23.131:6381
第一个IP 为新增的 redis 服务地址 , 第二个为集群内 的某个redis 集群地址。运行后的结果如下。
上图的输出后,我们查看一下集群内的信息
redis-cli -c -a 123456 -h 172.17.0.1 -p 6381 cluster nodes
命令输出:
从上图可以知道,6391 已经成为集群的一个master节点了,但是,redis 集群的存储时根据 哈希槽来分配存储位置的,上图很明显可以看出 6391 根本就没有分配到哈希槽,所以,在这个阶段上,6391 并不能在集群中起到任何作用,因此我们需要重新分配一下哈希槽。
5、给master节点分配哈希槽
// 方法一
redis-cli -a 123456 --cluster reshard 192.168.23.131:6391 --cluster-from 40d78aee9209f228365e441a6bc62ea0b7601f76,142bd0adf0a36a77a398eb22d848e241949683ca
// 方法二
redis-cli -a 123456 --cluster reshard 172.17.0.1:6391 --cluster-from 142bd0adf0a36a77a398eb22d848e241949683ca --cluster-to 286ed4ce493e832a078d6862444b605f472294ae --cluster-slots 2000
第一个为 新创建的master节点 --cluster-from 后面跟的是 原来集群中 master 节点的 id 值(多个用,隔开)。这个id 值可以通过 cluster nodes 查看到。
--cluster-from : 跟来源的master节点ID值
--cluster-to : 目标节点ID值
--cluster-slots : 分配多少哈希槽
// 你想移动多少个插槽(从1到16384)?
How many slots do you want to move (from 1 to 16384)?
这里可以输入 2000
// 接收节点ID是什么?
What is the receiving node ID?
请提前基础这个新创建的节点id
六、如何增加一个从节点
1、准备环节,和新增一个主节点一样
新增从节点端口 6392
2、创建配置文件、创建redis 容器
这个里跟创建主节点一样,就不一一填写了,最后得到的容器如下
3、给redis集群增加slave节点
进入集群内,并查看当前情况,如下:
现在要给 端口为 6391 的主节点增加一个从节点
七、移动master节点的哈希槽位
1、重新分配哈希槽 reshard 后面跟集群的某个服务器的ip 和端口
redis-cli -a 123456 --cluster reshard 172.17.0.1:6391
八、移除节点(主/从)
删除节点,比较简单,命令如下:
redis-cli -a 123456 --cluster del-node 172.17.0.1:6384 1183fa907276729afc3587ed8c318b05f895193e
del-node 后面跟需要删除的节点 服务地址与端口 并且加上 对应的id
上图是删除从节点的操作流程记录。如果需要删除主节点,需要先把主节点上面的哈希槽位移动到其他的 master节点,再进行删除。
参考文章:
Redis高可用架构—Redis集群(Redis Cluster)详细介绍https://baijiahao.baidu.com/s?id=1730440988136689035&wfr=spider&for=pc
集群搭建(Redis)(超详细)_redis集群搭建_一起去飞~的博客-CSDN博客(超详细)集群搭建(Redis)_redis集群搭建https://blog.csdn.net/CharmingC1/article/details/126806364
docker 进入redis容器内部 docker配置redis集群_mob6454cc6f4a4e的技术博客_51CTO博客docker 进入redis容器内部 docker配置redis集群,单机服务器,使用docker部署redis集群 首先获取redis镜像,dockerpullredis,我直接使用最新版本的redis,如果需要某一版本,则可以dockerpullredis:4.0.1获取成功后,可以通过dockerimages查看。 下面开始部署redis集群首先新建配置模板:vi redis-cluster.tmplporthttps://blog.51cto.com/u_16099262/6349816