前文中,我们已经对Redis的单节点哨兵的搭建方式做了演示和测试,相信大家已经了解了怎么操作,虽然是单节点,但基本已经满足了部分公司的日常需要,毕竟Redis集群不是什么项目都适用,用上了Redis,也未必需要使用哨兵,甚至集群。但今天,我们还是要把Redis哨兵集群的搭建方式给大家做个分享,万一用到了呢?话不多书,咱们直接上手。
学此篇必看内容:
Java开发 - 让你少走弯路的Redis的主从复制
Java开发 - 让你少走弯路的Redis主从实现单节点哨兵模式
这里,我们需要先准备4个Redis服务,分别是2主,2从,其详情如下:
节点 | IP | 端口 |
node1 | localhost | 6379 |
node2 | localhost | 6380 |
node1的从节点 | localhost | 6381 |
node2的从节点 | localhost | 6382 |
由于我们都是在本地模拟,所以IP可直接用localhost,生产环境可直接使用真是IP。
结构大家已经知道了,那么我们来准备这四个Redis的配置:
节点1
----------------------------------------------------
#配置端口
port 6379
#以守护进程模式启动
daemonize yes
#pid的存放文件
pidfile /var/run/redis_6379.pid
#日志文件名
logfile "redis_6379.log"
#rdb备份文件名
dbfilename "dump_6379.rdb"
#开启集群功能
cluster-enabled yes
#集群配置文件,节点自动维护
cluster-config-file nodes-6379.conf
#集群能够运行不需要集群中所有节点都是成功的
cluster-require-full-coverage no
节点2
----------------------------------------------------
#配置端口
port 6380
#以守护进程模式启动
daemonize yes
#pid的存放文件
pidfile /var/run/redis_6380.pid
#日志文件名
logfile "redis_6380.log"
#rdb备份文件名
dbfilename "dump_6380.rdb"
#开启集群功能
cluster-enabled yes
#集群配置文件,节点自动维护
cluster-config-file nodes-6380.conf
#集群能够运行不需要集群中所有节点都是成功的
cluster-require-full-coverage no
节点1的从节点
----------------------------------------------------
#配置端口
port 6381
#以守护进程模式启动
daemonize yes
#pid的存放文件
pidfile /var/run/redis_6381.pid
#日志文件名
logfile "redis_6381.log"
#rdb备份文件名
dbfilename "dump_6381.rdb"
#开启集群功能
cluster-enabled yes
#集群配置文件,节点自动维护
cluster-config-file nodes-6381.conf
#集群能够运行不需要集群中所有节点都是成功的
cluster-require-full-coverage no
节点2的从节点
----------------------------------------------------
#配置端口
port 6382
#以守护进程模式启动
daemonize yes
#pid的存放文件
pidfile /var/run/redis_6382.pid
#日志文件名
logfile "redis_6382.log"
#rdb备份文件名
dbfilename "dump_6382.rdb"
#开启集群功能
cluster-enabled yes
#集群配置文件,节点自动维护
cluster-config-file nodes-6382.conf
#集群能够运行不需要集群中所有节点都是成功的
cluster-require-full-coverage no
以上四个文件就是我们配置好的两对主从,但切记不要配置他们的主从关系,否则启动redis会报错:
如果配置了主从的,一定要去掉主从相关的配置,然后再启动 :
ps -ef | grep redis
此时可以看到四个Redis已经启动。
此时,你要先确定你的Redis的版本,Redis5之前,使用redis-trib.rb脚本搭建,5及之后的使用redis-cli,因为redis5.0之后已经将redis-trib.rb 脚本的功能全部集成到redis-cli中 。
如不确定版本,也可通过以下命令确认:
redis-cli --version
或
redis-server --version
博主使用的是低版本的redis,所以先试用redis-trib.rb脚本给大家演示,使用此脚本,需要ruby环境,不过我相信大家基本应该都是吧?不确定的可以运行此脚本查看:
ruby -v
能输出版本号就说明安装了此环境,没安装的请自行安装。
接着还需要gem安装下redis:
gem install redis
否则脚本执行会失败,报如下信息:
安装完成后,命令执行成功:
运行的时候要记得前面需要加上./,否则无法执行,此时你会看到创建集群失败了,这是因为创建集群需要至少6个redis节点,这是我们一开始没有想到的,为了不误导后来人,此时博主就在这里添加两个新的节点,最终的结构如下:
节点 | IP | 端口 |
node1 | localhost | 6379 |
node2 | localhost | 6380 |
node1的从节点 | localhost | 6381 |
node2的从节点 | localhost | 6382 |
node3 | localhost | 6383 |
node3的从节点 | localhost | 6384 |
redis配置如下:
节点3
----------------------------------------------------
#配置端口
port 6383
#以守护进程模式启动
daemonize yes
#pid的存放文件
pidfile /var/run/redis_6383.pid
#日志文件名
logfile "redis_6383.log"
#rdb备份文件名
dbfilename "dump_6383.rdb"
#开启集群功能
cluster-enabled yes
#集群配置文件,节点自动维护
cluster-config-file nodes-6383.conf
#集群能够运行不需要集群中所有节点都是成功的
cluster-require-full-coverage no
节点3的从节点
----------------------------------------------------
#配置端口
port 6384
#以守护进程模式启动
daemonize yes
#pid的存放文件
pidfile /var/run/redis_6384.pid
#日志文件名
logfile "redis_6384.log"
#rdb备份文件名
dbfilename "dump_6384.rdb"
#开启集群功能
cluster-enabled yes
#集群配置文件,节点自动维护
cluster-config-file nodes-6384.conf
#集群能够运行不需要集群中所有节点都是成功的
cluster-require-full-coverage no
启动新配置的redis并查看状态:
此时,我们重新运行集群的脚本命令:
./redis-trib.rb create --replicas 1 localhost:6379 localhost:6380 localhost:6383 localhost:6381 localhost:6382 localhost:6384
以上执行命令最终为:
./redis-trib.rb create --replicas 1 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6383 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6384
区别在于使用的IP不同。 如遇问题,请到下方问题里面寻找解决办法⬇️。
若是redis5,执行命令如下:
redis-cli -a 123456 --cluster create 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6383 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6384 1
先贴下成功的案例:
ERR Invalid node address specified: localhost:6379 (Redis::CommandError)
问题1和问题算是同一个问题,直接看问题2.
[ERR] Sorry, can't connect to node 192.168.0.103:6379
执行:
ps -ef | grep redis
创建集群的命令应该使用上面的IP,而不能随意使用,生产环境下使用真是IP即可,本地才会有此问题。由于差了不少资料,对redis设置了密码,添加了这两项:
#主从连接密码
masterauth 123456
#redis连接密码
requirepass 123456
建议设置一致,使用 redis-trib.rb脚本创建时命令中不能插入密码,所以要对此文件进行修改:
@r = Redis.new(:host => @info[:host], :port => @info[:port], :timeout => 60)
改为
@r = Redis.new(:host => @info[:host], :port => @info[:port], :timeout => 60, :password => "你的密码")
ERR Slot 0 is already busy (Redis::CommandError)
解决办法:
分别连接并清空slot槽,因为上面设置了密码,所以需要密码链接。
这之后,执行创建命令才成功,这是因为一开始创建4个集群的时候失败,导致slot槽已分配导致的,重置后再次执行创建命令则成功。
查看集群状态:
redis-cli -h 127.0.0.1 -p 6379 -a 123456 cluster node
图上可以看到主从配对,和我们一开始的设定是一样的,大家可以自己看看,slave后面那一串id匹配master前面的id。
查看集群信息:
redis-cli -h 127.0.0.1 -p 6379 -a 123456 cluster info
现在,我们来杀死一个id,就选择6380master的端口来杀死,看看会发生什么。
查看进程号:
ps -ef | grep redis
杀死6380对应的进程号:
kill 98534
然后查看集群节点信息:
接着我们发现,6380端口死了,它的从节点6382被提升为了新的master。
现在,重启6380端口并查看集群节点:
6380成了6382的从节点。从上到下,先自动选主,再切换主从,舒服~
我们现在再准备两个redis的配置文件,端口分别是6385主和6386从:
节点4
----------------------------------------------------
#配置端口
port 6385
#以守护进程模式启动
daemonize yes
#pid的存放文件
pidfile /var/run/redis_6385.pid
#日志文件名
logfile "redis_6385.log"
#rdb备份文件名
dbfilename "dump_6385.rdb"
#开启集群功能
cluster-enabled yes
#集群配置文件,节点自动维护
cluster-config-file nodes-6385.conf
#集群能够运行不需要集群中所有节点都是成功的
cluster-require-full-coverage no
节点4的从节点
----------------------------------------------------
#配置端口
port 6386
#以守护进程模式启动
daemonize yes
#pid的存放文件
pidfile /var/run/redis_6386.pid
#日志文件名
logfile "redis_6386.log"
#rdb备份文件名
dbfilename "dump_6386.rdb"
#开启集群功能
cluster-enabled yes
#集群配置文件,节点自动维护
cluster-config-file nodes-6386.conf
#集群能够运行不需要集群中所有节点都是成功的
cluster-require-full-coverage no
接着启动这两个新的redis配置:
redis-server redis_master4.conf
redis-server redis_slave4.conf
并查看redis运行状态:
已成功启动,下面我们把这两个redis添加到我们上面的集群中:
./redis-trib.rb add-node 127.0.0.1:6385 127.0.0.1:6379
./redis-trib.rb add-node 127.0.0.1:6386 127.0.0.1:6379
添加时,新的节点需要一个已经存在的节点的IP和port做为参照物来添加进去。
redis5.0使用此命令:
redis-cli -a 123456 -p 6379 --cluster add-node 127.0.0.1:6385 127.0.0.1:6379
redis-cli -a 123456 -p 6379 --cluster add-node 127.0.0.1:6386 127.0.0.1:6379
a后面位密码,新的节点需要一个已经存在的节点的IP和port做为参照物来添加进去。
添加成功,查看新添加的主节点:
给新添加的节点增加主从关系,redis-trib.rb只在创建集群的时候会帮我们自动设置主从关系,扩容操作就不会帮我们自动设置主从了,所以只能使用redis原生命令去设置主从关系,这个优点废,建议用高版本的去做。我们手动设置6376为6385的从节点:
redis-cli -h 127.0.0.1 -p 6386
auth 123456
#后面为6386的id
cluster replicate 365de2bd278e3e80147b366bad6fe13a86138148
退出并查看节点状态,此时,主从已经设置完成。
redis5的命令:
redis-cli -p 6386 -a 123456 cluster replicate 365de2bd278e3e80147b366bad6fe13a86138148
p是从节点的端口,a是密码,最后面是主节点的id。
眼尖的童鞋可能会看出来问题了,新添加主节点没有分配槽,额,好烦,因为redis5.0的命令会自动分配槽给新的节点,我为什么要选3.x的版本?啊?为啥?5.0分配时会有提示,和下面差不多。
下面开始迁移:
./redis-trib.rb reshard 127.0.0.1:6385
一共16384个槽,目前4个主节点,除以4是4096。 如果除不尽,需要做一个平衡,有微笑的误差,你在输入此命令时会有提示:
./redis-trib.rb rebalance ip:port
输入一个id就回车一次,结束用done。
然后就开始了漫长的迁移过程,等一会儿就好了。
终于结束了,我们来看看迁移情况:
可以看到主节点都已经分配了槽。
扩容说完了,我们来说说缩容,新添加的节点怎么去除呢?比如我的这个节点太卡,我想换个新的节点,要去除节点,就要先把槽给别的节点才行:
./redis-trib.rb reshard --from 365de2bd278e3e80147b366bad6fe13a86138148 --to 994325203cc78fc79894e8ef9427244ba18be267 --slots 4096 127.0.0.1:6385
一次性把所有槽都给6379:
接着就开始迁移槽了:
然后结束:
查看目前的槽分配情况:
6385已经没有槽了,此时可以移除了,但是移除的时候,如果有从节点,需要先移除 从节点:
./redis-trib.rb del-node 127.0.0.1:6386 d344bd2a331a20653402239030a32dd2dc30aa54
接着移除主节点6385:
./redis-trib.rb del-node 127.0.0.1:6385 365de2bd278e3e80147b366bad6fe13a86138148
redis5.0这么做:
redis-cli -p 6379 -a 123 --cluster reshard --cluster-from 被移除的节点id --cluster-to 槽需要迁移到的节点id --cluster-slots 需要迁移的槽数量 IP:port
此时,查看集群的状态:
redis-cli -h 127.0.0.1 -p 6379 -a 123456 cluster nodes
6385和6386已经没有了,接下来查看运行的redis有哪些:
ps -ef | grep redis
此时6385和6386的redis服务器已经被关闭了。
spring:
redis:
database: 0
password: 123456
sentinel:
master: mymaster
# 四个redis-sentinel
nodes: ip:port,ip:port,ip:port,ip:port
单节点下,哨兵只要监听主节点,就可以找到所有的主节点的从节点。
集群下,哨兵必须同时监听所有的主节点,才能监听到所有的节点:
#配置端口
port 26379
# 设置为守护进程模式,可先注释,看投票选主的过程
#daemonize yes
#日志文件名
logfile "redis_sentinel.log"
#存放备份文件以及日志等文件的目录
dir "/opt/redis/data"
# redis_sentinel表示hostname,自己随意取名
# 数字1表示当主机宕机后,在从机中进行投票选主,票数大于1的晋升为主机
sentinel monitor redis_sentinel1 127.0.0.1 6380 1
sentinel monitor redis_sentinel2 127.0.0.1 6381 1
sentinel monitor redis_sentinel3 127.0.0.1 6382 1
#30秒ping不通主节点的信息,主观认为master宕机
sentinel down-after-milliseconds redis_sentinel1 30000
sentinel down-after-milliseconds redis_sentinel2 30000
sentinel down-after-milliseconds redis_sentinel3 30000
#故障转移后重新主从复制,1表示串行,>1并行
sentinel parallel-syncs redis_sentinel1 1
sentinel parallel-syncs redis_sentinel2 1
sentinel parallel-syncs redis_sentinel3 1
#故障转移三分钟内没有完成,认为转移失败
sentinel failover-timeout redis_sentinel1 180000
sentinel failover-timeout redis_sentinel2 180000
sentinel failover-timeout redis_sentinel3 180000
这就是博主之前为什么只讲了单节点sentinel的原因,需要sentinel集群的话就上面一模一样的sentinel多配几个,就可以了,可以自己试试。
spring:
redis:
cluster:
nodes:
- 127.0.0.1:6379
- 127.0.0.1:6380
- 127.0.0.1:6381
- 127.0.0.1:6382
- 127.0.0.1:6383
- 127.0.0.1:6384
max-redirects: 6 #节点数量
jedis:
pool:
max-active: 16 #最大的连接数
max-wait: 3000 #最大的等待时间
max-idle: 8 #最大空闲数
min-idle: 0 #最小空闲数
结尾给大家推荐几篇写得不错的redis集群博客:
Redis高可用实现
Redis详解(九)------ 哨兵(Sentinel)模式详解
Redis详解(十)------ 从零开始搭建集群_从零搭建redis集群
redis 主从模式、哨兵(sentinel) 配置、cluster(集群)联系与区别
到此,这篇Redis的集群搭建就给大家介绍完了,可能还存在一些细节上的不足,如果你刚好看到,刚好用到,有什么疑问的话,都可以评论区留言讨论,博主一定知无不言,言无不尽。最后,祝愿大家都能成为优秀的Java开发工程师,加油哦!