您的位置:js12345金沙官网登入 > 网络编程 > Redis Cluster机制分析

Redis Cluster机制分析

2020-03-29 09:49

节点握手

Redis集群的MOVED和ASK转向

1、 MOVED转向:客户端向集群中的任意节点发送命令请求,节点先会对命令请求进行分析,如果命令请求是集群可以执行的命令,那么节点会查找这个命令的键所在的哈希槽。如果查找到的哈希槽正好是接收该命令请求的节点负责处理,那么节点直接执行命令,如果查找的哈希槽不在当前节点上,节点将查自身内部所保存的哈希槽到节点ID的映射记录,并向客户端回复一个MOVED转向。

2、 ASK转向:在将哈希槽10从节点A迁移到B的过程中,客户端发送一个命令请求到A节点,A节点检查命令请求的键是否在节点上,如果在则执行命令请求,否则,A节点会响应一个ASK定向给客户端,告知客户端目标节点是B节点。客户端在收到ASK定向之后,向B节点发送一个ASKING的命令,然后再发送命令请求。B节点如果没有收到ASKING的命令,是不会处理客户端的命令请求。

以下是该算法所使用的参数:

Redis集群的键分布模型:Redis的键空间被分割为16384个哈希槽,集群的最大节点数也是16384(推荐最大节点数为1000个左右)。集群为每个节点分配一定的哈希槽,客户端根据(CRC16(key) mod 16384)的值得到哈希槽,并根据哈希槽和节点ID 的映射关系找到目标节点。

另一方面, 当节点需要让客户端仅仅在下一个命令请求中转向至另一个节点时, 节点向客户端返回 ASK 转向。

Redis集群的容错机制

1、主从复制:集群中的主节点可以有多个从节点,他们的功能相同,数据一致,当主节点故障,集群选举该主节点的一个从节点当主节点,保障集群能继续使用。

2、节点失效检测:
(1) 当节点向另外一个节点发送PING命令,但目标节点未能在给定时限内返回回复,那么发送PING命令的节点会将目标节点标记为PFAIL(possible failtrue)。
(2) 每当节点向其它节点发送PING命令时,都会随机的广播三个它所知道的节点信息,信息包括PFAIL和FAIL。
(3) 当节点收到其他节点发过来的信息,会记录下那些已经被其他节点标记为失效的节点,这个过程叫失效报告(failure report)。
(4) 如果节点已经将某个节点标记为PFAIL,并根据失效报告知道集群中其他节点也认为这个节点进入失效,那么会将该节点的状态标识为FAIL。
(5) 一旦某个节点被标识为FAIL状态,关于这个节点已失效的信息就会被广播到这个集群,所有接收到这个信息的节点都会将失效节点标识为FAIL状态。
节点的FAIL状态会在以下两种情况下被移除:
(1)被标识的是从节点,从节点重新上线后标识被移除。保持一个从节点的FAIL状态没什么意义,因为它不处理任何哈希槽,一个从节点处于FAIL状态,不能提升为主节点。
(2)如果一个主节点被打上FAIL标识后,经过了节点超时时限的4倍又10秒钟后,针对这个节点的故障尚未移除,主节点重新上线,FAIL标识被移除。

3、集群状态检测:集群进入FAIL状态有以下两种情况,
(1)至少有一个哈希槽不可用,因为负责这个槽的节点进入FAIL状态。
(2)集群中的大部分的节点都进入PFAIL状态,集群也会进入FAIL状态。

4、节点选举机制:一个从节点被选举成为一个主节点的条件:
(1)这个节点是失效节点的从节点。
(2)已失效主节点处理的槽数为空。
(3)从节点的数据被认为是可靠的。也就是,主从节点之间的复制
连接的断线时长不能超过节点超时时限(node timeout)乘以
REDIS_CLUSTER_SLAVE_VALIDITY_MULT 常量得出的积。
以上条件满足后,从节点向其他主节点发送授权请求,请求让自己成为新的主节点。如果授权请求满足以下属性,集群中的主节点将向从节点返回授权:
(1)发送请求的是一个从节点,并且它所属的主节点是FAIL状态。
(2)已下线主节点的从节点中,这个节点的ID在排序中是最小。
(3)这个从节点正常,没有标识为PFAIL或FAIL。
一旦从节点获得大多数主节点的授权,那它会执行以下故障转移:
(1)通过PONG数据包告知其他节点,这个节点已经是主节点了。
(2)通过PONG数据包告知其他节点,这个节点是一个已升级的从
节点。
(3)接管已失效主节点的哈希槽。
(4)向所有节点广播一个PONG数据包,加速其他节点识别该节点。
所有其他节点根据新的主节点更新相应配置:
(1)所有被新的主节点接管的哈希槽都会被更新。
(2)已下线主节点的所有从节点会察觉到 PROMOTED 标志,开始对新的主节点进行复制。
(3)如果已下线的主节点重新回到上线状态, 那么它会察觉到 PROMOTED 标志, 并将自身调整为现任主节点的从节点

如果一个从节点满足了以上的所有条件, 那么这个从节点将向集群中的其他主节点发送授权请求, 询问它们, 是否允许自己升级为新的主节点。

Redis集群数据弱一致性

在以下条件下,Redis集群可能会丢失已经被执行过的写入命令。
1、异步复制:
(1)客户端向主节点发送一条写命令;
(2)主节点执行写命令并向客户端返回执行结果;
(3)主节点将刚刚执行的写命令复制给它的从节点。如果主节点在此时失效,数据还未复制到从节点,会导致数据的丢失。
2、网络分裂:产生网络分裂时,集群会分成大多数一方和少数一方,
假如少数一方包括A节点和C客户端,当C客户端写入A节点时,
大多数方已经推举了A节点的从节点A1为新的主节点,此时,C
客户端写入A节点的命令会丢失。

Redis 集群实现了单机 Redis 中, 所有处理单个数据库键的命令。

Redis集群的扩容策略

Redis集群支持在线重配置,它包括添加一个新的节点到集群或者从集群上删除一个节点。新添加节点等同于将其他已存在在节点的哈希槽迁移到一个新节点里面,删除一个节点等同于将该节点上的哈希槽迁移到其他节点上。Cluster的一些命令负责管理集群节点的槽转换表。
• CLUSTER ADDSLOTS slot1 [slot2] ... [slotN] 新增节点
• CLUSTER DELSLOTS slot1 [slot2] ... [slotN] 删除节点
• CLUSTER SETSLOT slot NODE node 将指定的槽指派给节点
• CLUSTER SETSLOT slot MIGRATING node 将给定的槽迁出节点
• CLUSTER SETSLOT slot IMPORTING node 将给定的槽迁入节点
当一个哈希槽被设置为MIGRATING时,原来持有这个槽的节点仍然会处理关于这个槽的命令请求,但只有该命令所处理的键仍然存在于节点时,节点才会处理这个命令请求。如果命令所处理的键不在节点上,那么节点将向客户端返回一个ASK转向请求,告知客户端要将命令请求发送到哈希槽的迁移目标上。
当一个哈希槽被设置为IMPORTING时,节点仅在接收到ASKING命令后才处理该哈希槽的命令请求。
如果客户端没有向节点发送 ASKING 命令, 那么节点会使用 -MOVED 转向错误将命令请求转向至真正负责处理这个槽的节点。
假设现在我们有A和B两个节点,并且我们想将槽10从节点A迁移到节点B,于是我们:
• 向节点 B 发送命令 CLUSTER SETSLOT 10 IMPORTING A
• 向节点 A 发送命令 CLUSTER SETSLOT 10 MIGRATING B
每当客户端向其他节点发送关于哈希槽10的的命令请求时,这些节点都会向客户端返回指向节点A的转向信息:
(1)如果要处理的键在槽10里面,那么该命令由A节点处理。
(2)如果命令要处理的键不在槽10里面(比如新增一个键值),那么这个命令由B处理。

在上面列出的三行信息中, 从左到右的各个域分别是: 节点 ID , IP 地址和端口号, 标志, 最后发送 PING 的时间, 最后接收 PONG 的时间, 连接状态, 节点负责处理的槽。

Redis集群是一个分布式、容错的Redis实现,集群实现了单机Redis中所有单个数据键的命令,它是普通单机Redis的一个子集。

因为过期的失效报告会被移除, 所以主节点要将某个节点标记为 FAIL 的话, 必须以最近接收到的失效报告作为根据。

当我们说一个集群处于“稳定”状态时, 指的是集群没有在执行重配置操作, 每个哈希槽都只由一个节点进行处理。

MIGRATE target_host target_port key target_database id timeout

虽然不是必须的, 但一个客户端应该记录下“槽 3999 由节点 127.0.0.1:6381 负责处理“这一信息, 这样当再次有命令需要对槽 3999 执行时, 客户端就可以加快寻找正确节点的速度。

容错

要理解 Redis 集群如何将槽从一个节点移动到另一个节点, 我们需要对 CLUSTER 命令的各个子命令进行介绍, 这些命理负责管理集群节点的槽转换表。

重配置指的是将某个/某些槽从一个节点移动到另一个节点。

当节点需要让一个客户端长期地将针对某个槽的命令请求发送至另一个节点时, 节点向客户端返回 MOVED 转向。

以下是每个节点都有的关联信息, 并且节点会将这些信息发送给其他节点:

总结

节点之间使用 Gossip 协议 来进行以下工作:

因为 Redis 集群只使用 0 号数据库, 所以当 MIGRATE 命令被用于执行集群操作时, target_database 的值总是 0 。target_database 参数的存在是为了让 MIGRATE 命令成为一个通用命令, 从而可以作用于集群以外的其他功能。

Redis 集群的键空间被分割为 16384 个槽, 集群的最大节点数量也是 16384 个。

GET x-MOVED 3999 127.0.0.1:6381

以下是负责将键映射到槽的算法:

接收到客户端 ASKING 命令的节点将为客户端设置一个一次性的标志, 使得客户端可以执行一次针对 IMPORTING 状态的槽的命令请求。

一旦配置处理完毕, 集群会进入以下两种状态的其中一种:

集群状态检测

当一个槽被设置为 IMPORTING 状态时, 节点仅在接收到 ASKING 命令之后, 才会接受关于这个槽的命令请求。

在之前介绍 MOVED 转向的时候, 我们说除了 MOVED 转向之外, 还有另一种 ASK 转向。

Redis 集群实现的功能子集

显式地向所有节点广播一个 PONG 数据包, 加速其他节点识别这个节点的进度, 而不是等待定时的 PING / PONG 数据包。

在将来, 用户也许可以通过 MIGRATE COPY 命令, 在集群的计算节点中执行针对多个数据库键的只读操作, 但集群本身不会去实现那些需要将多个数据库键在多个节点中移来移去的复杂多键命令。

这说明即使集群中只有一部分哈希槽不能正常使用, 整个集群也会停止处理任何命令。

第二个检查是必须的, 因为要将一个节点从 PFAIL 状态改变为 FAIL 状态, 必须要有大部分主节点进行投票表决, 但是, 当集群中的大部分主节点都进入失效状态时, 单凭一个两个节点是没有办法将一个节点标记为 FAIL 状态的。

一个 Redis 客户端可以向集群中的任意节点发送命令请求。 节点会对命令请求进行分析, 如果该命令是集群可以执行的命令, 那么节点会查找这个命令所要处理的键所在的槽。

从节点选举

注意, 即使客户端出现 Bug , 过早地将槽 8 映射到了节点 B 上面, 但只要这个客户端不发送 ASKING 命令, 客户端发送命令请求的时候就会遇上 MOVED 错误, 并将它转向回节点 A 。

每当集群发生配置变化时, 集群中的每个节点都会对它所知道的节点进行扫描。

与此同时, 一个特殊的客户端 redis-trib 以及 Redis 集群配置程序会将节点 A 中槽 8 里面的键移动到节点 B 。

在集群的生命周期中, 如果一个带有 PROMOTED 标识的主节点因为某些原因转变成了从节点, 那么该节点将丢失它所带有的 PROMOTED 标识。

除了 MOVED 转向错误之外, 一个客户端还应该可以处理稍后介绍的 ASK 转向错误。

如果客户端没有向节点发送 ASKING 命令, 那么节点会使用 -MOVED 转向错误将命令请求转向至真正负责处理这个槽的节点。

主节点和从节点使用完全相同的服务器实现, 它们的功能也完全一样, 但从节点通常仅用于替换失效的主节点。不过, 如果不需要保证“先写入,后读取”操作的一致性, 那么可以使用从节点来执行只读查询。

端回复一个 MOVED 错误。

一个主节点可以有任意多个从节点, 这些从节点用于在主节点发生网络断线或者节点失效时, 对主节点进行替换。

HASH_SLOT = CRC16(key) mod 16384

CRC16 算法所产生的 16 位输出中的 14 位会被用到。在我们的测试中, CRC16 算法可以很好地将各种不同类型的键平稳地分布到 16384 个槽里面。

然而, 除了 PING 之外, 节点会拒绝其他所有并非来自集群节点的数据包。

这个节点是已下线主节点的从节点。已下线主节点负责处理的槽数量非空。从节点的数据被认为是可靠的, 也即是, 主从节点之间的复制连接的断线时长不能超过节点超时时限乘以 REDIS_CLUSTER_SLAVE_VALIDITY_MULT 常量得出的积。

错误信息包含键 x 所属的哈希槽 3999 , 以及负责处理这个槽的节点的 IP 和端口号 127.0.0.1:6381 。 客户端需要根据这个 IP 和端口号, 向所属的节点重新发送一次 GET 命令请求。

如果被标记为 FAIL 的是从节点, 那么当这个节点重新上线时, FAIL 标记就会被移除。保持从节点的 FAIL 状态是没有意义的, 因为它不处理任何槽, 一个从节点是否处于 FAIL 状态, 决定了这个从节点在有需要时能否被提升为主节点。如果一个主节点被打上 FAIL 标记之后, 经过了节点超时时限的四倍时间, 再加上十秒钟之后, 针对这个主节点的槽的故障转移操作仍未完成, 并且这个主节点已经重新上线的话, 那么移除对这个节点的 FAIL 标记。

新的主节点由已下线主节点属下的所有从节点中自行选举产生, 以下是选举的条件:

因为这种转向只针对 16384 个槽中的其中一个槽, 所以转向对集群造成的性能损耗属于可接受的范围。

如果发送授权请求的从节点满足以下属性, 那么主节点将向从节点返回 FAILOVER_AUTH_GRANTED 授权, 同意从节点的

在第二种情况中, 如果故障转移未能顺利完成, 并且主节点重新上线, 那么集群就继续使用原来的主节点, 从而免去管理员介入的必要。

附录 A 中给出了集群所使用的 CRC16 算法的实现。

在已下线主节点的所有从节点中, 这个从节点的节点 ID 在排序中是最小的。

节点失效检测

节点总是应答来自集群连接端口的连接请求, 并对接收到的 PING 数据包进行回复, 即使这个 PING 数据包来自不可信的节点。

在目前的实现中, 节点会将接收到的信息广播至集群中的其他所有节点, 在将来的实现中, 可能会使用 bloom filter 或者其他算法来优化这一操作。

集群节点属性

推荐的最大节点数量为 1000 个左右。

每个主节点都负责处理 16384 个哈希槽的其中一部分。

从一个外部客户端的视角来看, 在某个时间点上, 键 key 要么存在于节点 A , 要么存在于节点 B , 但不会同时存在于节点 A 和节点 B 。

如果客户端接收到 ASK 转向, 那么将命令请求的发送对象调整为转向所指定的节点。先发送一个 ASKING 命令,然后再发送真正的命令请求。不必更新客户端所记录的槽 8 至节点的映射: 槽 8 应该仍然映射到节点 A , 而不是节点 B 。

这种节点识别机制通过防止不同的 Redis 集群因为 IP 地址变更或者其他网络事件的发生而产生意料之外的联合, 从而使得集群更具健壮性。

从集群中移除一个节点, 等于将被移除节点的所有槽移动到集群的其他节点上面去。

集群的容错功能是通过使用主节点和从节点两种角色的节点来实现的:

从客户端的角度来看, ASK 转向的完整语义如下:

已下线主节点的所有从节点会察觉到 PROMOTED 标志, 并开始对新的主节点进行复制。

算法的名称: XMODEM (又称 ZMODEM 或者 CRC-16/ACORN)结果的长度: 16 位多项数: 1021 (也即是 x16 + x12 + x5 + 1)初始化值: 0000反射输入字节: False发射输出 CRC : False用于 CRC 输出值的异或常量: 0000该算法对于输入 "123456789" 的输出: 31C3

持有键值对数据。记录集群的状态,包括键到正确节点的映射。自动发现其他节点,识别工作不正常的节点,并在有需要时,在从节点中选举出新的主节点。

金沙澳门娱乐网址,Redis 集群中的节点有以下责任:

引言

至少有一个哈希槽不可用,因为负责处理这个槽的节点进入了 FAIL 状态。集群中的大部分主节点都进入下线状态。当大部分主节点都进入 PFAIL 状态时,集群也会进入 FAIL 状态。

Redis 集群是一个分布式、容错的 Redis 实现, 集群可以使用的功能是普通单机 Redis 所能使用的功能的一个子集。

一旦节点 A 针对槽 8 的迁移工作完成, 节点 A 在再次收到针对槽 8 的命令请求时, 就会向客户端返回 MOVED 转向, 将关于槽 8 的命令请求长期地转向到节点 B 。

这个文档是正在开发中的 Redis 集群功能的规范文档, 文档分为两个部分:

以上信息的其中一部分可以通过向集群中的任意节点发送 CLUSTER NODES 命令来获得。

这种机制将使得节点 A 不再创建关于槽 8 的任何新键。

MOVED 转向

第一部分介绍目前已经在 unstable 分支中实现了的那些功能。第二部分介绍目前仍未实现的那些功能。

添加一个新节点到集群, 等于将其他已存在节点的槽移动到一个空白的新节点里面。

如果命令要处理的键已经存在于槽 8 里面, 那么这个命令将由节点 A 处理。如果命令要处理的键未存在于槽 8 里面, 那么这个命令由节点 B 处理。

Redis 集群不像单机 Redis 那样支持多数据库功能, 集群只使用默认的 0 号数据库, 并且不能使用 SELECT 命令。

本文由js12345金沙官网登入发布于网络编程,转载请注明出处:Redis Cluster机制分析

关键词: