在前面的文章,已经写过redis主从架构和redis哨兵架构了,那么本文介绍的是redis集群架构,redis集群是当前大型互联网公司常用的架构模式了,由于它的强大高效而又便捷的功能,得到了广泛的使用。
哨兵架构
卡槽定位算法
请求重定向
Redis集群节点间的通信机制
meet:某个节点发送meet给新加入的节点,让新节点加入集群中,然后新节点就会开始与其他节点进行通信;
ping:每个节点都会频繁给其他节点发送ping,其中包含自己的状态还有自己维护的集群元数据,互相通过ping交换元数据(类似自己感知到的集群节点增加和移除,hash slot信息等);
pong: 对ping和meet消息的返回,包含自己的状态和其他信息,也可以用于信息广播和更新;
fail: 某个节点判断另一个节点fail之后,就发送fail给其他节点,通知其他节点,指定的节点宕机了。
gossip协议的优点在于元数据的更新比较分散,不是集中在一个地方,更新请求会陆陆续续,打到所有节点上去更新,有一定的延时,降低了压力;缺点在于元数据更新有延时可能导致集群的一些操作会有一些滞后。
gossip通信的10000端口
网络抖动现象
比如,当某个节点出现问题时,需要一定的传播时间让多数master节点认为该节点确实不可用,才能标记标记该节点真正下线。Redis集群的节点下线包括两个环节:主观下线和客观下线
主观下线:当节点A在cluster-node-timeout时间内和节点B通信(ping-pong消息)一直失败,则节点A认为节点B不可用,标记为主观下线,并将状态消息传播给其他节点。
客观下线:当一个节点被集群内多数master节点标记为主观下线后,则触发客观下线流程,标记该节点真正下线。
Redis集群选举原理
slave节点发现自己的master节点状态为fail
将自己记录的集群currentEpoch加1,并广播FAILOVER_AUTH_REQUEST 信息
其他节点收到该信息,只有master响应,判断请求者的合法性,并发送FAILOVER_AUTH_ACK,对每一个epoch只发送一次ack
尝试failover的slave收集master返回的FAILOVER_AUTH_ACK
slave收到超过半数master的ack后变成新Master(这里解释了集群为什么至少需要三个主节点,如果只有两个,当其中一个挂了,只剩一个主节点是不能选举成功的)
slave广播Pong消息通知其他集群节点。
如上选举步骤,可能会存在这样一种问题,比如说,我三台集群节点,每台master节点有两台slave节点,当一台服务器宕机了,两个slave节点同时向其他两台master节点发送选举命令,前面有说到每台master选举只有一票的权利,当你给slave节点投了一票,就不能给另外一台slave节点投票了,恰好两台master节点分别给不同slave投了一票,这个时候两个slave节点票数一样了,那该怎么办呢?
如上,在延续一个问题,要是一直投票选举都没有结果,那这集群岂不是废掉了?
延迟计算公式:
集群脑裂数据丢失问题
min-slaves-to-write 1 //写数据成功最少同步的slave数量,这个数量可以模仿大于半数机制配置,比如集群总共三个节点可以配置1,加上leader就是2,超过了半数
集群中每个节点负责处理一部分卡槽,比如下场景
MasterA节点处理0-5460个哈希槽
MasterB节点处理5461-10922个哈希槽
MasterC节点处理10923-16383个哈希槽
例如,我现在想设置一个key:叫sunny123
set sunny123 666
让集群正常启动最少三个主节点,因为资源有限,我这里用三台服务器,每台服务器一个master节点和一个slave节点,为了让大家好区分,对应的redis节点的ip和端口对应关系如下
#服务器1
192.168.137.22:6379
192.168.137.22:6380
#服务器2
192.168.137.23:6379
192.168.137.23:6380
#服务器3
192.168.137.24:6379
192.168.137.24:6380
yum install -y gcc
第一种方式在官网下载可能会很慢,也可以尝试通过下面的网址下载redis
http://download.redis.io/releases/
那我这里就直接选择第二种方式进行下载
//进入目录
cd usr/local/
//创建目录
mkdir software
//进入我们刚刚创建目录(这里是我个人习惯,喜欢将安装包放入到这个文件夹中)
cd software
下载redis-5.0.3.tar.gz
wget http://download.redis.io/releases/redis-5.0.3.tar.gz
如果下载出现 wget 未找到命令 (因为linux里面没有这个命令,我们安装这个命令才能下载)
yum -y install wget
如下图则就下载好啦
tar xzf redis-5.0.3.tar.gz
// 我们进入redis文件夹
cd redis-5.0.3
// 编译redis,如下图所示,就代表已经编译成功啦
make
#三台服务器都创建
mkdir -p usr/local/software/redis-cluster
#进入目录
cd usr/local/software/redis-cluster
#每台服务器不同的端口创建不同的文件夹
#服务器1
mkdir 8001 8002
#服务器2
mkdir 8003 8004
#服务器3
mkdir 8005 8006
cp usr/local/software/redis-5.0.3/redis.conf usr/local/software/redis-cluster/800*
#修改配置文件
vim redis.conf
#后台启动
daemonize yes
#redis端口(分别对每个机器的端口号进行设置)
port 8001
# 把pid进程号写入pidfile配置的文件
pidfile /var/run/redis_8001.pid
#指定数据文件存放位置,必须要指定不同的目录位置,不然会丢失数据
dir /usr/local/software/redis-cluster/8001/
#启动集群模式
cluster-enabled yes
#集群节点信息文件,这里8001最好和port对应上
cluster-config-file nodes-8001.conf
#集群通讯超时时间
cluster-node-timeout 10000
#bind绑定的是自己机器网卡的ip,如果有多块网卡可以配多个ip,代表允许客户端通过机器的哪些网卡ip去访问,内网一般可以不配置bind,注释掉即可
# bind 127.0.0.1
#关闭保护模式
protected-mode no
#开启aof持久化机制
appendonly yes
如果要设置密码需要增加如下配置:requirepass zhuge (设置redis访问密码)
masterauth zhuge (设置集群节点间访问密码,跟上面一致)
启动实例
#启动实例
/usr/local/software/redis-5.0.3/src/redis-server usr/local/software/redis-cluster/800*/redis.conf
#查看是否启动成功
ps -ef | grep redis
如上图,我们三台服务器的主从两个节点redis节点,全部都启动成功了
/usr/local/software/redis-5.0.3/src/redis-cli -a sunny --cluster create --cluster-replicas 1 192.168.137.22:8001 192.168.137.22:8002 192.168.137.23:8003 192.168.137.23:8004 192.168.137.24:8005 192.168.137.24:8006
# 临时关闭防火墙
systemctl stop firewalld
# 禁止开机启动
systemctl disable firewalld
如上图则创建成功了。
#-a访问服务端密码,-c表示集群模式,指定ip地址和端口号
/usr/local/software/redis-5.0.3/src/redis-cli -a sunny -c -h 192.168.137.22 -p 8001
cluster info
查看节点列表
还有一个注意事项,如果当你把三台服务器全部关闭了,下次再次去启动redis的时候,可不要去执行创建集群命令了哦,你只需要将三台服务器的所有redis节点启动完毕,集群会自动帮你映射好,为什么呢?原因就在nodes-端口.conf这个文件里面,每个节点的文件夹下都有这个文件,启动好之后,redis会自动找到这个文件,然后帮你集群哈。
前面我们的集群已经搭建完毕了,那我们现在来点更加高端操作,redis集群的水平扩展,由于我前面已经有3台服务器的redis节点了,我在这里再创建一台服务器,用于水平扩展,创建的redis节点与上方一样,创建集群文件夹,然后在分别创建新的两个端口文件夹,接着将redis的配置copy到两个端口文件夹,然后修改配置即可,我这里只是大概说一下,就不演示如何操作了
查看集群信息
启动扩展redis所有节点
/usr/local/software/redis-5.0.3/src/redis-cli -a sunny --cluster add-node 192.168.137.25:8007 192.168.137.22:8001
分配卡槽
/usr/local/software/redis-5.0.3/src/redis-cli -a sunny --cluster reshard 192.168.137.22:8001
如上图,它询问我们需要移动多少卡槽给新加入的节点上,这里可以根据自己的需求自己设置,我这里设置的500卡槽
接着,就会继续询问,将这500个hash卡槽分配到哪一个master节点上,这里需要填写节点的ID
all: 代表从集群的所有master节点中各抽取部分卡槽到指定的节点上
done: 指定某个节点抽取卡槽
添加集群Slave节点
/usr/local/software/redis-5.0.3/src/redis-cli -a sunny --cluster add-node 192.168.137.25:8008 192.168.137.22:8001
然后再次查看集群节点的状态
如图所示,还是一个master节点,没有被分配任何的hash槽
从节点分配
#进入8008客户端
/usr/local/software/redis-5.0.3/src/redis-cli -a sunny -c -h 192.168.137.25 -p 8008
##后面这串id为8007的节点id
cluster replicate b7125af0035e93e5f0bc2fa35aa5b52a4cfd44d5
/usr/local/software/redis-5.0.3/src/redis-cli -a sunny --cluster del-node 192.168.137.25:8008 ca566c87246145016ea80f82354236630a2a2a80
删除集群Master节点
/usr/local/software/redis-5.0.3/src/redis-cli -a sunny --cluster reshard 192.168.137.25:8007
这里是需要把数据移动到哪?8001的主节点id
/usr/local/software/redis-5.0.3/src/redis-cli -a sunny --cluster del-node 192.168.137.25:8007 b7125af0035e93e5f0bc2fa35aa5b52a4cfd44d5
我是黎明大大,我知道我没有惊世的才华,也没有超于凡人的能力,但毕竟我还有一个不屈服,敢于选择向命运冲锋的灵魂,和一个就是伤痕累累也要义无反顾走下去的心。
如果您觉得本文对您有帮助,还请关注点赞一波,后期将不间断更新更多技术文章


