Redis之集群

redis集群是redis提供的分布式数据库方案,集群通过分片来进行数据共享,并提供复制和故障转移功能。
节点
一个redis集群通常由多个节点组成,在刚开始的时候,每个节点都是相互独立的,他们都处于一个只包含自己的集群当中,要组建一个真正可工作的集群,我们必须将各个独立的节点连接起来,构成一个包含多个节点的集群。
命令格式如下:
CLUSTER MEET <ip><port>
向一个节点发送CLUSTER MEET命令,可以让节点域ip和port所指定的节点进行握手,握手成功时,node节点就会将ip和port所指定的节点添加到node节点当前所在的集群中
启动节点
在这里插入图片描述
redis服务器在启动时会根据cluster-enabled配置选项是否为yes来决定是否开启服务器的集群模式
CLUSTER MEET命令的实现
通过向节点A发送CLUSTER MEET命令,客户端可以让接收命令的节点A将另一个节点B添加到节点A当前所在的集群里面:
1、节点A会为节点B创建一个clusterNode结构,并将该结构添加到自己的clusterState.nodes字典里面
2、节点A将根据CLUSTER MEET命令给定的IP地址和端口号,向节点B发送一条MEET消息
3、如果一切顺利,节点B将接受到节点A发送的MEET消息,节点B会为节点A创建一个clusterNode结构,并将该结构添加到自己的clusterState.nodes字典里面
4、节点B向节点A返回一条PONG消息
5、如果一切顺利,节点A将接收到节点B返回的PONG消息,通过这条消息节点A可以知道节点B已经成功地接收到了自己发送地MEET消息
6、节点A向节点B返回一条PING消息
7、如果一切顺利,节点B将接收到节点A返回地PING消息,通过这条PING消息,节点B可以知道节点A已经成功地接收到了自己返回地PONG消息,握手完成。
在这里插入图片描述
之后,节点A会将节点B地信息通过Gossip协议传播给集群中地其他节点,让其他节点也与节点B进行握手。
槽指派
redistribution集群通过分片地方式来保存数据库中地键值对:集群地整个数据库被分为16384个槽(slot),数据库中地每个键都属于这16384个槽地其中一个,集群中地每个节点可以处理0个或最多16384个槽。
当数据库中地16384个槽都有节点在处理时,集群处于上线状态,反之,如果有任何一个槽没有被处理,那么整个集群处于下线状态
通过向节点发送CLUSTER ADDSLOTS命令,可以将一个或多个槽指派给节点负责:
CLUSTER ADDSLOTS <slot>[slot …]
记录节点地槽指派信息
clusterNode结构地slots属性和numslot属性记录了节点负责处理哪些槽
slots属性是一个二进制位数组,长度为2048个字节,共包含16384个二进制位
在这里插入图片描述
上图表示该节点处理0-7槽
传播节点地槽指派信息
一个节点除了会将自己负责处理地槽记录在clusterNode结构地slots属性和numslots属性之外,它还会将自己的slots数组通过消息发送给其他节点,告诉其他节点自己处理哪些槽。
记录集群中所有槽的指派信息
在clusterState结构中的slots数组记录了集群中所有16384个槽的指派信息
slots数组包含16384个项,每个数组项都是一个指向clusterNode结构的指针:
1、如果slots[i]指针指向NULL,那么表示槽i尚未指派给任何节点
2、如果slots[i]指针指向一个clusterNode结构,那么表示槽i已经指派给了clusterNode结构所代表的节点
在集群中执行命令
在对数据库中的16384个槽都进行了指派之后,集群就会进入上线状态,这时客户端就可以向集群中的节点发送数据命令了。
当客户端向节点发送与数据库键有关的命令时,接受命令的节点会计算出命令要处理的数据库键属于哪个槽,并检查这个槽是否指派给了自己
在这里插入图片描述
MOVED错误
当节点发现键所在的槽并非由自己负责处理的时候,节点就会向客户端发送一个MOVED错误,引导客户端转向正在负责槽的节点。
MOVED slot ip port
一个集群客户端通常会与多个集群节点建立套接字连接,所谓的节点转向只不过是换一个套接字发送命令。
如果客户端尚未与想要转向的节点创建套接字连接,那么客户端会先根据
MOVED提供的IP地址和端口号来连接节点,然后再进行转向。
重新分片
redis集群的重新分片操作可以将任意数量已经指派给某个节点的槽改为指派给另一个节点,并且相关槽所属的键值对也会从源节点被移动到目标节点。
重新分片操作可以在线进行,在重新分片的过程中,集群不需要下线,并且源节点和目标节点都可以继续处理命令请求。
重新分片的实现原理
redis集群的重新分片操作是由redis的集群管理软件redis-trib负责执行的,redis提供了进行重新分片所需的所有命令,而redis-trib则通过向源节点和目标节点发送命令来进行重新分片操作。
redis-trib对集群的单个槽slot进行重新分片的步骤如下:
1、redis-trib对目标节点发送CLUSTER SETLOT <slot> IMPORTING <soruce_id>,让目标节点准备好从源节点导入槽slot的键值对
2、redis-trib向源节点发送CLUSTER SETSLOT <slot>MIGRATING <target_id>命令,让源节点准备号将属于槽slot的键值对迁移至目标节点。
3、redis-trib对源节点发送CLUSTER GETKEYSINLOT <slot> <count>命令,获得最多count个属于槽slot的键值对的键名
4、对于步骤3获得的每个键名,redis-trib都向源节点发送一个MIGRATE <target_ip> <target_port> <key_name> 0 <timeou>命令,将被选中的键原子地从源节点迁移至目标节点
5、重复执行步骤3和步骤4,知道源节点保存地所有属于槽slot地键值对都被迁移至目标节点为止
6、redis-trib向集群中地任意一个节点发送CLUSTER SETSLOT <slot> NODE <target_id>命令,将槽slot指派给目标节点,这一指派信息会通过消息发送至整个集群。
在这里插入图片描述
在这里插入图片描述
ASK错误和MOVED错误的区别
MOVED:代表槽的负责权已经从一个节点转移到了另一个节点:在客户端收到关于槽i的MOVED错误之后,客户端每次遇到关于槽i的命令请求时,都可以直接将命令请求发送至MOVED错误所指向的节点,因为该节点就是目前负责槽i的节点
ASK:两个节点在迁移槽的过程中使用的一种临时措施:在客户端收到关于槽i的ASK错误之后,客户端只会在接下来的一次命令请求中将关于槽i的命令请求发送至ASK错误所指示的节点,但这种转向不会对客户端今后发送关于槽i的命令请求产生任何影响。
复制与故障转移
redis集群中的节点分为主节点和从节点,其中主节点用于处理槽,而从节点则用于复制某个主节点,并在被复制的主节点下线时,代替下线主节点继续处理命令请求。
故障检测
集群中的每个节点都会定期地向集群中地其他节点发送PING消息,以此来检测对方是否下线,如果接收PING消息的节点没有在规定的时间内,向发送PING消息的节点返回PONG消息,那么发送PING消息的节点就会将接收PING消息的节点标记为疑似下线,在自己的clusterState.nodes字典中找到该节点对应的clusterNode结构,并在该结构的flags属性中打开 REDIS_NODE_PFALL标识。集群中的各个节点会通过互相发送消息的方式来交换集群中的各个节点的状态信息,当一个主节点A通过消息得知主节点B认为主节点C进入了疑似下线状态时,主节点A会在自己的clusterState.nodes字典中找到主节点C所对应的clusterNode结构,并将主节点B的下线报告添加到clusterNode结构的fail_reports链表里面。
如果一个集群里面,半数以上负责处理槽的主节点都将某个主节点x报告未疑似下线,那么这个主节点x将被标记为已下线,将主节点x标记为已下线的节点会向集群中广播一条关于主节点x的FALL消息,大多有收到这条FALL消息的节点都会立即将主节点x标记为已下线。
故障转移
当一个从节点发现自己正在复制的主节点进入了已下线状态时,从节点将开始对下线主节点进行故障转移,以下时步骤:
1、复制下线主节点的所欲从节点里面,会有一个从节点被选中
2、被选中的从节点会执行SLAVEOF no one命令,成为新的主节点
3、新的主节点会撤销所有对已下线主节点的槽指派,并将这些槽指派全部指派给自己
4、新的主节点向集群广播一条PONG消息,这条PONG消息可以让集群中的其他节点立即知道这个节点已经有从节点变成了主节点,并且这个主节点已经接管了原本由已下线节点负责处理的槽
5、新的主节点开始接收和自己负责处理的槽有关的命令请求
选举新的主节点
选举办法
1、集群的配置纪元时一个自增计数器,它的初始值为0
2、当集群里的某个节点开始一次故障转移操作时,集群配置纪元的值会被增一
3、对于每个配置纪元,集群里每个负责处理槽的主节点都有一次投票的机会,而第一个向主节点要求投票的从节点将获得主节点的投票
4、当从节点发现自己正在复制的主节点进入已下线状态时,从节点会向集群广播一条CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST 消息,要求收到这条消息、并且具有投票权的主节点向这个从节点投票。
5、如果一个主节点具有投票权,并且这个主节点尚未投票给其他从节点,那么主节点将向要求投票的从节点返回一条CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK消息,表示这个主节点支持从节点成为新的主节点
6、每个参与选举的从节点都会接收CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK消息,并根据自己收到了多少条这种消息来统计自己获得了多少主节点的支持
7、如果集群里有N个具有投票权的主节点,那么当一个从节点收集到大于等于N/2+1张支持票时,这个从节点就会当选为新的主节点
8、因为在每一个配置纪元里面, 每个具有投票权的主节点只能投一次票,所以如果有N个主节点进行投票,那么具有大于等于N/2+1张支持票的从节点只会有一个,这确保了新的主节点只会有一个
9、如果一个配置纪元里面没有从节点能收集到足够多的支持票,那么集群进入一个新的纪元,并在此进行选举,知道选出新的主节点为止

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值