第17章 集群
redis集群是redis提供的分布式数据库方案,集群通过分片来进行数据共享,并提供复制和故障转移功能。
17.1 节点
一个redis集群通常由多个节点组成,在刚开始的时候,每个节点都是相互独立的,它们都处于一个只包含自己的集群当中,要组建一个真正可工作的集群,我们必须将各个独立的节点连接起来,构成一个包含多个节点的集群。
通过向节点A发送cluster meet命令,客户端可以让接收命令的节点A将另一个节点B添加到节点A当前所在的集群里面:
Cluster meet <ip> <port>
17.2 槽指派
redis集群通过分片的方式来保存数据库中的键值对:集群的整个数据库被分为16384个槽(slot),数据库中的每个键都属于这个16384个槽的其中一个,集群中的每个节点可以处理0个或最多16384个槽。
当数据库中的16384个槽都有节点在处理时,集群处于上线状态(OK);相反地,如果数据库中有任何一个槽没有得到处理,那么集群处于下线状态(fail)。
集群中的每个节点都会将自己的slots数组通过消息发送给集群中的其他节点,并且每个接收到slots数组的节点都会将数组保存到相应节点的clusternode结构里面,因此集群中的每个节点都会知道数据库中的16384个槽分别被指派给集群中的哪些节点。
17.3 在集群中执行命令
当客户端指向节点发送与数据库键有关的命令时,接受命令的节点会计算出命令要处理的数据库键属于哪个槽,并检查这个槽是否指派给了自己。
- 如果键所在的槽正好就指派给了当前节点,那么节点直接执行这个命令;
- 如果键所在的槽并没有指派给当前节点,那么节点会向客户端返回一个moved错误,指引看客户端转向(redirect)至正确的节点,并再次发送之前想要执行的命令。
节点和单机服务器在数据库方面的一个区别是,节点只能使用0号数据库,而单机redis服务器则没有这一限制。
17.4 重新分片
redis集群的重新分片操作可以将任意数量已经指派给某个节点的槽改为指派给另一个节点,并且相关槽所属的兼职对也会从源节点被移动到目标节点。
重新分片的实现原理
redis集群的重新分片操作是由redis的集群管理软件redis-trib负责执行的,redis提供了进行重新分片所需的所有命令,而redis-trib则通过向源节点和目标节点发送命令来进行重新分片操作。
17.5 ASK错误
如果节点收到一个关于键key的命令请求,并且键key所属的槽i正好就指派给了这个节点,那么节点会尝试在自己的数据库里查找键key,如果找到了的话,节点就直接执行客户端发送的命令。
与此相反,如果节点没有自己的数据库里找到键key,那么节点会检查自己的slots[i],看到键key所属的槽i是否正在进行迁移,如果槽i的确在进行迁移的话,那么节点会向客户端发送一个ASK错误,引导客户端到正在导入槽i的节点去查找键key.
ASK错误和MOVED错误的区别
它们的区别在于:
- Moved错误代表槽的负责权已经从一个节点转移到了另一个节点:在客户端收到关于关于槽i的moved错误之后,客户端每次遇到关于槽i的命令请求时,都可以直接将命令请求发送地址moved错误锁指向的节点,因为该节点就是目前负责槽i的节点。
- 与此相反,ASK错误只是两个节点在迁移槽的过程中的一种临时措施:在客户端收到关于槽i的ASK错误之后,客户端只会在接下来的一次命令请求中关于槽i的命令请求发送至ASK错误锁指示的节点,但这种转向不会对客户端今后发送关于槽i的命令请求产生任何影响,客户端仍然会将关于槽i的命令请求发送至目前负责处理槽i的节点,除非ASK错误在出现。
17.6 复制与故障转移
Redis集群中的节点分为主节点(master)和从节点(slave),其中主节点用于处理槽,而从节点则用于复制某个主节点,并在被复制的主节点下线时,代替下线主节点继续处理命令请求。
故障转移
当一个从节点发现自己正在复制的主节点进入了已下线状态时,从节点将开始对下线主节点进行故障转移,以下是故障转移的执行步骤:
- 1.复制下线主节点的所有从节点里面,会有一个从节点被选中。
- 2.被选中的从节点会执行SLAVEof no one命令,成为新的主节点。
- 3.新的主节点会撤销所有对已下线主节点的槽指派,并将这些槽全部指派给自己。
- 4.新的主节点向集群广播一条PONG消息,这条PONG消息可以让集群中的其他节点立即知道这个节点已经由从节点变成了主节点,并且这个主节点已经接管了原本由已下线节点负责处理的槽。
- 5.新的主节点开始接收和自己负责处理的槽有关的命令请求,故障转移完成。
选举新的主节点
基于Raft算法的领头选举方法实现的。
17.7 消息
集群中的各个节点通过发送和接受消息(message)来进行通信,我们称为发送消息的节点为发送者(sender),接受消息的节点为接受者,节点发送的消息主要有以下五种:
- MEET消息:请求接收者加入到发送者当前所处的集群里面
- PING消息:检验被选中的节点是否在线
- PONG消息:发送者用来确认消息
- FAIL消息:广播节点B已下线的状态消息
- PUBLISH消息:publish命令