Redis Cluster学习笔记2

继上一篇,本文将探讨下Redis Cluster更多的原理和特性。本文的内容来自于官方文档和后面的参考文献。

1. 节点握手机制

节点总是接受并应答来自集群连接端口的连接请求, 并对接收到的PING数据包进行回复PONG,即使这个PING数据包来自不可信的节点。除了PING之外, 节点会拒绝其他所有并非来自集群节点的数据包。
要让一个节点承认另一个节点同属于一个集群, 只有以下两种方法:
一个节点可以通过向另一个节点发送 MEET 信息, 来强制让接收信息的节点承认发送信息的节点为集群中的一份子。 一个节点仅在管理员显式地向它发送 CLUSTER MEET ip port 命令时, 才会向另一个节点发送 MEET 信息。
另外, 如果一个可信节点向另一个节点传播第三者节点的信息, 那么接收信息的那个节点也会将第三者节点识别为集群中的一份子。 也即是说, 如果 A 认识 B , B 认识 C , 并且 B 向 A 传播关于 C 的信息, 那么 A 也会将 C 识别为集群中的一份子, 并尝试连接 C 。
这意味着如果我们将一个/一些新节点添加到一个集群中, 那么这些新节点最终会和集群中已有的其他所有节点连接起来。
这种节点识别机制通过防止不同的 Redis 集群因为 IP 地址变更或者其他网络事件的发生而产生意料之外的联合, 从而使得集群更具健壮性。
当节点的网络连接断开时, 它会主动连接其他已知的节点。

2. 集群中的主和从

集群的容错功能是通过使用主节点和从节点两种角色的节点来实现的:但从节点通常仅用于替换失效的主节点。不过, 如果不需要保证“先写入,后读取”操作的一致性(read-after-write consistency), 那么可以使用从节点来执行只读查询。为了使在部分节点失败或者大部分节点无法通信的情况下集群仍然可用,所以集群使用了主从复制模型,每个节点都会有N-1个复制品.
在我们例子中具有A,B,C三个节点的集群,在没有复制模型的情况下,如果节点B失败了,那么整个集群就会以为缺少5501-11000这个范围的槽而不可用。然而如果在集群创建的时候(或者过一段时间)我们为每个节点添加一个从节点A1,B1,C1,那么整个集群便有三个master节点和三个slave节点组成,这样在节点B失败后,集群便会选举B1为新的主节点继续服务,整个集群便不会因为槽找不到而不可用了。不过当B和B1 都失败后,集群仍然是不可用的.
Redis 并不能保证数据的强一致性. 这意味这在实际中集群在特定的条件下可能会丢失写操作。第一个原因是因为集群是用了异步复制. 写操作过程:
客户端向主节点B写入一条命令.
主节点B向客户端回复命令状态.
主节点将写操作复制给他得从节点 B1, B2 和 B3.
主节点对命令的复制工作发生在返回命令回复之后, 因为如果每次处理命令请求都需要等待复制操作完成的话, 那么主节点处理命令请求的速度将极大地降低 —— 我们必须在性能和一致性之间做出权衡。
Redis 集群另外一种可能会丢失命令的情况是集群出现了网络分区, 并且一个客户端与至少包括一个主节点在内的少数实例被孤立。.
举个例子 假设集群包含 A 、 B 、 C 、 A1 、 B1 、 C1 六个节点, 其中 A 、B 、C 为主节点, A1 、B1 、C1 为A,B,C的从节点, 还有一个客户端 Z1
假设集群中发生网络分区,那么集群可能会分为两方,大部分的一方包含节点 A 、C 、A1 、B1 和 C1 ,小部分的一方则包含节点 B 和客户端 Z1 .
Z1仍然能够向主节点B中写入, 如果网络分区发生时间较短,那么集群将会继续正常运作,如果分区的时间足够让大部分的一方将B1选举为新的master,那么Z1写入B中得数据便丢失了.
注意, 在网络分裂出现期间, 客户端 Z1 可以向主节点 B 发送写命令的最大时间是有限制的, 这一时间限制称为节点超时时间(node timeout), 是 Redis 集群的一个重要的配置选项:

3. 节点的失效检测

当一个节点向另一个节点发送 PING 命令, 但是目标节点未能在给定的时间内(node timeout)返回 PING 命令的回复时, 那么发送命令的节点会将目标节点标记为 PFAIL (possible failure)。
而每次当节点对其他节点发送 PING 命令的时候, 它都会随机地广播三个它所知道的节点的信息, 这些信息里面的其中一项就是说明节点是否已经被标记为 PFAIL 或者 FAIL 。
当节点接收到其他节点发来的信息时, 它会记下那些被其他节点标记为失效的节点, 这称为失效报告(failure report)。
如果节点已经将某个节点标记为 PFAIL , 并且根据节点所收到的失效报告显式, 集群中的大部分其他主节点也认为那个节点进入了失效状态, 那么节点会将那个失效节点的状态标记为 FAIL 。
简单来说, 一个节点要将另一个节点标记为失效, 必须先询问其他节点的意见, 并且得到大部分主节点的同意才行。因为过期的失效报告会被移除, 所以主节点要将某个节点标记为 FAIL 的话, 必须以最近接收到的失效报告作为根据。
在以下两种情况中, 节点的 FAIL 状态会被移除:
a). 如果被标记为 FAIL 的是从节点, 那么当这个节点重新上线时, FAIL 标记就会被移除。
b). 从节点的 FAIL 状态是没有意义的, 因为它不处理任何槽, 一个从节点是否处于 FAIL 状态, 决定了这个从节点在有需要时能否被提升为主节点。
c). 如果一个主节点被打上 FAIL 标记之后, 经过了节点超时时限的四倍时间, 再加上十秒钟之后, 针对这个主节点的槽的故障转移操作仍未完成, 并且这个主节点已经重新上线的话, 那么移除对这个节点的 FAIL 标记。
d). 在第二种情况中, 如果故障转移未能顺利完成, 并且主节点重新上线, 那么集群就继续使用原来的主节点, 从而免去管理员介入的必要。

4. 从节点选举

一旦某个主节点进入 FAIL 状态, 如果这个主节点有一个或多个从节点存在, 那么其中一个从节点会被升级为新的主节点, 而其他从节点则会开始对这个新的主节点进行复制。
新的主节点由已下线主节点属下的所有从节点中自行选举产生, 以下是选举的条件:
· 这个节点是已下线主节点的从节点。
· 已下线主节点负责处理的槽数量非空。
​ · 从节点的数据被认为是可靠的, 也即是, 主从节点之间的复制连接(replication link)的断线时长不能超过节点超时时限(node timeout)乘以 REDIS_CLUSTER_SLAVE_VALIDITY_MULT常量。
如果一个从节点满足了以上的所有条件, 那么这个从节点将向集群中的其他主节点发送授权请求, 询问它们, 是否允许自己(从节点)升级为新的主节点。如果发送授权请求的从节点满足以下属性, 那么其他主节点将向从节点返回 FAILOVER_AUTH_GRANTED 授权, 同意从节点的升级:
· 发送授权请求的是一个从节点, 并且它所属的主节点处于 FAIL 状态。
· 在已下线主节点的所有从节点中, 这个从节点的节点 ID 在排序中是最小的。
· 这个从节点处于正常的运行状态: 它没有被标记为 FAIL 状态, 也没有被标记为 PFAIL 状态。
一旦某个从节点在给定的时限内得到大部分主节点的授权, 它就会开始执行以下故障转移操作:
· 通过 PONG 数据包(packet)告知其他节点, 这个节点现在是主节点了。
· 通过 PONG 数据包告知其他节点, 这个节点是一个已升级的从节点(promoted slave)。
· 接管(claiming)所有由已下线主节点负责处理的哈希槽。
· 显式地向所有节点广播一个 PONG 数据包, 加速其他节点识别这个节点的进度, 而不是等待定时的 PING / PONG 数据包。
所有其他节点都会根据新的主节点对配置进行相应的更新,特别地:
· 所有被新的主节点接管的槽会被更新。
· 已下线主节点的所有从节点会察觉到 PROMOTED 标志, 并开始对新的主节点进行复制。
· 如果已下线的主节点重新回到上线状态, 那么它会察觉到 PROMOTED 标志, 并将自身调整为现任主节点的从节点。
· 在集群的生命周期中, 如果一个带有 PROMOTED 标识的主节点因为某些原因转变成了从节点, 那么该节点将丢失它所带有的 PROMOTED标识。

^^
参考:
http://www.redis.cn/topics/cluster-tutorial.html
http://redis.readthedocs.org/en/latest/topic/cluster-spec.html
https://github.com/HunanTV/redis-cerberus/wiki/Redis-%E9%9B%86%E7%BE%A4%E4%BB%A3%E7%90%86%E5%9F%BA%E6%9C%AC%E5%8E%9F%E7%90%86%E4%B8%8E%E4%BD%BF%E7%94%A8

Posted in Database, MySQL.