分布式系统设计(4)

先说一下前面三节介绍的内容,如果需要请参考,

第一节介绍数据分布方式:http://www.cnblogs.com/jacksu-tencent/p/3405680.html

第二节介绍副本控制协议:http://www.cnblogs.com/jacksu-tencent/p/3407712.html

第三节介绍基于Lease的分布式cache系统:http://www.cnblogs.com/jacksu-tencent/p/3409646.html

通过第三节的介绍,大家应该对Lease机制有一定的了解了,本节主要介绍Lease的本质,以及通过lease机制,如何来判断节点的状态,最后介绍在hdfs、chuby和zookeeper中如何应用lease机制。

Lease机制本质

Lease 是由颁发者授予的在某一有效期内的承诺。主要有两方面的承诺

一方面颁发者一旦发出 lease,则无论接受方是否收到,也无论后续接收方处于何种状态,只要 lease 不过期,颁发者一定严守承诺;

另一方面,接收方在 lease 的有效期内可以使用颁发者的承诺,但一旦 lease 过期,接收方一定不能继续使用颁发者的承诺。

就是只要lease不过期,颁发者一定严守承诺;一旦lease过期,接收方一定不能继续使用颁发者的承诺

Lease机制容错能力

首先,通过引入有效期,Lease 机制非常好的容错网络异常。 Lease 颁发过程只依赖于网络可以单向通信,即使接收方无法向颁发者发送消息,也不影响 lease的颁发。由于 lease 的有效期是一个确定的时间点,lease 的语义与发送 lease 的具体时间无关,所以同一个 lease 可以被颁发者不断重复向接受方发送。即使颁发者偶尔发送 lease 失败,颁发者也可以简单的通过重发的办法解决。一旦 lease 被接收方成功接受,后续 lease 机制不再依赖于网络通信,即使网络完全中断 lease 机制也不受影响。

再者,Lease 机制能较好的容错节点宕机。如果颁发者宕机,则宕机的颁发者通常无法改变之前的承诺,不会影响 lease 的正确性。在颁发者机恢复后,如果颁发者恢复出了之前的 lease 信息,颁发者可以继续遵守 lease 的承诺。如果颁发者无法恢复 lease信息,则只需等待一个最大的 lease 超时时间就可以使得所有的 lease 都失效,从而不破坏 lease 机制。例如上节中的 cache 系统的例子中,一旦服务器宕机,肯定不会修改元数据,重新恢复后,只需等待一个最大的 lease 超时时间,所有节点上的缓存信息都将被清空。对于接受方宕机的情况,颁发者不需要做更多的容错处理,只需等待 lease 过期失效,就可以收回承诺,实践中也就是收回之前赋予的权限、身份等。

最后,lease 机制不依赖于存储。颁发者可以持久化颁发过的 lease 信息,从而在宕机恢复后可以使得在有效期的 lease 继续有效。但这对于 lease 机制只是一个优化,如之前的分析,即使颁发者没有持久化 lease 信息,也可以通过等待一个最大的 lease 时间的方式使得之前所有颁发的 lease 失效,从而保证机制继续有效。

颁发方和接收方时间不同步该如何处理呢???

分为两种情况:

如果颁发者的时钟比接收者的时钟慢,则当接收者认为 lease 已经过期的时候,颁发者依旧认为 lease 有效。接收者可以用在 lease 到期前申请新的 lease 的方式解决这个问题。

如果颁发者的时钟比接收者的时钟快,则当颁发者认为 lease 已经过期的时候,接收者依旧认为 lease 有效,颁发者可能将 lease颁发给其他节点,造成承诺失效,影响系统的正确性。对于这种时钟不同步,实践中的通常做法是将颁发者的有效期设置得比接收者的略大,只需大过时钟误差就可以避免对 lease 的有效性的影响。

基于lease机制如何确定节点状态

通过一个例子来讨论这个问题:

在一个 primary-secondary 架构的系统中,有三个节点 A、B、C 互为副本,其中有一个节点为 primary,且同一时刻只能有一个 primary 节点。另有一个节点 Q 负责判断节点 A、B、C的状态,一旦 Q 发现 primary 异常,节点 Q 将选择另一个节点作为 primary。假设最开始时节点 A为 primary,B、C 为 secondary。节点 Q 需要判断节点 A、B、C 的状态是否正常。

通过心跳无法很好判断节点状态

节点 A、B、C 可以周期性的向 Q 发送心跳信息,如果节点 Q 超过一段时间收不到某个节点的心跳则认为这个节点异常。这种方法的问题是假如节点 Q 收不到节点 A 的心跳,除了节点 A 本身的异常外,也有可能是因为节点 Q 与节点 A 之间的网络中断导致的。在工程实践中,更大的可能性不是网络中断,而是节点 Q 与节点 A 之间的网络拥塞造成的所谓“瞬断”,“瞬断”往往很快可以恢复。另一种原因甚至是节点 Q 的机器异常,以至于处理节点 A 的心跳被延迟了,以至于节点 Q 认为节点 A 没有发送心跳。假设节点 A 本身工作正常,但 Q 与节点 A 之间的网络暂时中断,节点 A 与节点 B、C 之间的网络正常。此时节点 Q 认为节点 A 异常,重新选择节点 B 作为新的 primary,并通知节点 A、B、C 新的 primary 是节点 B。由于节点 Q 的通知消息到达节点 A、B、C 的顺序无法确定,假如先到达 B,则在这一时刻,系统中同时存在两个工作中的 primary,一个是 A、另一个是 B。假如此时 A、B 都接收外部请求并与 C 同步数据,会产生严重的数据错误。上述即所谓“双主”问题

双主问题的解决

由中心节点向其他节点发送 lease,若某个节点持有有效的 lease,则认为该节点正常可以提供服务。节点 A、 B、 C 依然周期性的发送 heart beat 报告自身状态,节点 Q 收到 heart beat后发送一个 lease,表示节点 Q 确认了节点 A、B、C 的状态,并允许节点在 lease 有效期内正常工作。节点 Q 可以给 primary 节点一个特殊的 lease,表示节点可以作为 primary 工作。一旦节点 Q 希望切换新的 primary,则只需等前一个 primary 的 lease 过期,则就可以安全的颁发新的 lease 给新的primary 节点,而不会出现“双主”问题。

一个中心节点风险解决

借助chubby 和 zookeeper

lease 的有效期时间选择

常选择的 lease 时长是 10 秒级别,这是一个经过验证的经验值,实践中可以作为参考并综合选择合适的时长。

GFS 中的 Lease

GFS 中使用 Lease 确定 Chuck 的 Primary 副本。 Lease 由 Master 节点颁发给 primary 副本,持有Lease 的副本成为 primary 副本。Primary 副本控制该 chuck 的数据更新流量,确定并发更新操作在chuck 上的执行顺序。GFS 中的 Lease 信息由 Master 在响应各个节点的 HeartBeat 时附带传递piggyback)。对于每一个 chuck,其上的并发更新操作的顺序在各个副本上是一致的,首先 master选择 primary 的顺序,即颁发 Lease 的顺序,在每一任的 primary 任期内,每个 primary 决定并发更新的顺序,从而更新操作的顺序最终全局一致。当 GFS 的 master 失去某个节点的 HeartBeat 时,只需待该节点上的 primary chuck 的 Lease 超时,就可以为这些 chuck 重新选择 primary 副本并颁发 lease

Chubby 与 Zookeeper 中的 Lease

Chubby 中有两处使用到 Lease 机制。

我们知道 chubby 通过 paxos 协议实现去中心化的选择 primary 节点。一旦某个节点获得了超过半数的节点认可,该节点成为 primary 节点,其余节点成为 secondary 节点。Secondary节点向 primary 节点发送 lease,该 lease 的含义是:“承诺在 lease 时间内,不选举其他节点成为 primary节点”。只要 primary 节点持有超过半数节点的 lease,那么剩余的节点就不能选举出新的 primary。一旦 primary 宕机,剩余的 secondary 节点由于不能向 primary 节点发送 lease,将发起新的一轮 paxos选举,选举出新的 primary 节点。

除了 secondary 与 primary 之间的 lease,在 chubby 中,primary 节点也会向每个 client 节点颁发

lease。该 lease 的含义是用来判断 client 的死活状态,一个 client 节点只有只有合法的 lease,才能与chubby 中的 primary 进行读写操作。一个 client 如果占有 chubby 中的一个节点锁后 lease 超时,那么这个 client 占有的 chubby 锁会被自动释放,从而实现了利用 chubby 对节点状态进行监控的功能。另外, chubby 中 client 中保存有数据的 cache,故此 chubby 的 primary 为 cache 的数据颁发 cache lease,该过程与 前一节介绍的基于 lease 的 cahce 机制完全类似。虽然相关文献上没有直接说明,但笔者认为,chubby 的 cache  lease 与 primary 用于判断 client 死活状态的 lease 是可以合并为同一个 lease的,从而可以简化系统的逻辑。

与 Chubby 不同, Zookeeper 中的 secondary 节点(在 zookeeper 中称之为 follower)并不向 primary节点(在 zookeeper 中称之为 leader)发送 lease, zookeeper 中的 secondary 节点如果发现没有 primary节点则发起新的 paxos 选举,只要 primary 与 secondary 工作正常,新发起的选举由于缺乏多数secondary 的参与而不会成功。与 Chubby 类似的是, Zookeeper 的 primary 节点也会向 client 颁发 lease,lease 的时间正是 zookeeper 中的 session 时间。在 Zookeeper 中,临时节点是与 session 的生命期绑定的, 当一个 client 的 session 超时,那么这个 client 创建的临时节点会被 zookeeper 自动删除。通过监控临时节点的状态,也可以很容易的实现对节点状态的监控。在这一点上,zookeeper 和 chubby 完全是异曲同工。

下一节简单有效的副本管理机制quorum

posted @ 2013-11-09 13:00  TheBug  阅读(2014)  评论(1编辑  收藏  举报