Lease机制
大多数数据分布方式都会有一个瓶颈问题--中心服务器存储维护着元数据,系统中其他的节点通过访问它读取,修改元数据。这样,中心服务器节点的性能就容易成为系统的瓶颈。解决方法也有多种,你可能会搭建一个集群专门存储元数据,并对外进行读写。但这样又要涉及到数据的一致性问题。本文将介绍被广泛应用于各种实际的分布式系统中的最重要的分布式协议--Lease机制。
基本原理:
中心服务器在向各节点发送数据时同时向节点颁发一个lease。每个lease具有一个有效期,和信用卡上的有效期类似,lease上的有效期通常是一个明确的时间点,例如12:00:10,一旦真实时间超过这个时间点,则lease过期失效。在lease的有效期内,中心服务器保证不会修改对应数据的值。因此,节点收到数据和lease后,将数据加入本地Cache,一旦对应的lease超时,节点将对应的本地cache数据删除。中心服务器在修改数据时,首先阻塞所有新的读请求,并等待之前为该数据发出的所有lease超时过期,然后修改数据的值。
上述机制可以保证各个节点上的cache与中心服务器上的中心始终一致。这是因为中心服务器节点在发送数据的同时授予了节点对应的lease,在lease有效期内,服务器不会修改数据,从而客户端节点可以放心的在lease有效期内cache数据。上述lease机制可以容错的关键是:服务器一旦发出数据及lease,无论客户端是否收到,也无论后续客户端是否宕机,也无论后续网络是否正常, 服务器只要等lease超时,就可以保证对应的客户端节点不会再继续cache数据,从而可以放心的修改数据而不会破坏cache的一致性。
优化点一:
服务器在修改元数据时首先要阻塞读请求并等待lease超时,这是为了防止发出新的lease从而引起活锁。优化方法很简单:进入修改流程后,我们对读请求只返回数据,不颁发lease。进一步优化,我们可以颁发lease,但有效期设置为已发出到lease的最大有效期。这样,客户端节点可以继续缓存元数据,并且不会造成活锁。不过,实际情况中,第一种优化就足够了。因为等待超时的时间会被优化点二大大减少。
优化点二:
服务器在修改元数据时需要等待所有的lease过期超时,从而造成修改元数据的操作时延大大增大。优化的方法是,在等待所有的lease过期的过程中,服务器主动通知各个持有lease的节点放弃lease并清除cache中的数据,如果服务器收到客户端返回的确认放弃lease的消息, 则服务器不需要在等待该lease超时。该过程中,如果因为异常造成服务器通知失败或者客户端节点发送应答消息失败,服务器只需依照原本的流程等待lease超时即可,而不会影响协议的正确性。
优化点三:
Lease机制依赖于有效期(常选择的 lease 时长是10秒级别),这就要求颁发者和接收者的时钟是同步的。一方面,如果颁发者的时钟比接收者的时钟慢,则当接收者认为lease已经过期的时候,颁发者依旧认为lease有效。接收者可以用在lease到期前申请新的lease的方式解决这个问题。另一方面,如果颁发者的时钟比接收者的时钟快,则当颁发者认为lease已经过期的时候,接收者依旧认为lease有效,颁发者可能将lease颁发给其他节点,造成承诺失效,影响系统的正确性。对于这种时钟不同步,实践中的通常做法是将颁发者的有效期设置得比接收者的略大,只需大过时钟误差就可以避免对lease的有效性的影响。