分布式系统设计(3)
本节主要通过设计一个分布式的cache系统,来介绍Lease的使用,甚至可以作为一个分布式cache系统,在工程中使用。如果在介绍中涉及到的一些概念,可以参考前面两篇本文:
http://www.cnblogs.com/jacksu-tencent/p/3405680.html
http://www.cnblogs.com/jacksu-tencent/p/3407712.html
背景
在一个分布式系统中,有一个中心服务器节点,中心服务器存储、维护着一些数据,这些数据是系统的元数据。系统中其他的节点通过访问中心服务器节点读取、修改其上的元数据。由于系统中各种操作都依赖于元数据,如果每次读取元数据的操作都访问中心服务器节点,那么中心服务器节点的性能成为系统的瓶颈。
要求
首先为此,设计一种元数据 cache,在各个节点上cache 元数据信息,从而减少对中心服务器节点的访问,提高性能。
另一方面,系统的正确运行严格依赖于元数据的正确,这就要求各个节点上 cache 的数据始终与中心服务器上的数据一致,cache中的数据不能是旧的脏数据。
最后,设计的 cache 系统要能最大可能的处理节点宕机、网络中断等异常,最大程度的提高系统的可用性。
基于lease的设计基本原理
中心服务器在向各节点发送数据时同时向节点颁发一个 lease。每个 lease 具有一个有效期,和信用卡上的有效期类似,lease 上的有效期通常是一个明确的时间点,例如 12:00:10,一旦真实时间超过这个时间点,则 lease 过期失效。这样 lease 的有效期与节点收到 lease 的时间无关,节点可能收到 lease 时该 lease 就已经过期失效。这里首先假设中心服务器与各节点的时钟是同步的,下节中讨论时钟不同步对 lease 的影响。中心服务器发出的 lease 的含义为:在 lease 的有效期内,中心服务器保证不会修改对应数据的值。因此,节点收到数据和 lease 后,将数据加入本地 Cache,一旦对应的 lease 超时,节点将对应的本地 cache数据删除。中心服务器在修改数据时,首先阻塞所有新的读请求,并等待之前为该数据发出的所有lease 超时过期,然后修改数据的值。
大家思考一下该原理的缺陷偶。。。。
服务器与客户端节点交互基本流程
基于 lease 的 cache,客户端节点读取元数据
1. 判断元数据是否已经处于本地 cache 且 lease 处于有效期内
1.1 是:直接返回 cache 中的元数据
1.2 否:向中心服务器节点请求读取元数据信息
1.2.1 服务器收到读取请求后,返回元数据及一个对应的 lease
1.2.2 客户端是否成功收到服务器返回的数据
1.2.2.1 失败或超时:退出流程,读取失败,可重试
1.2.2.2 成功:将元数据与该元数据的 lease 记录到内存中,返回元数据
基于 lease 的 cache,客户端节点修改元数据流程
1. 节点向服务器发起修改元数据请求。
2. 服务器收到修改请求后,阻塞所有新的读数据请求,即接收读请求,但不返回数据。
3. 服务器等待所有与该元数据相关的 lease 超时。
4. 服务器修改元数据并向客户端节点返回修改成功。
优点
可以保证各个节点上的 cache 与中心服务器上的中心始终一致。这是因为中心服务器节点在发送数据的同时授予了节点对应的 lease,在 lease 有效期内,服务器不会修改数据,从而客户端节点可以放心的在 lease 有效期内 cache 数据。上述 lease 机制可以容错的关键是:服务器一旦发出数据及 lease,无论客户端是否收到,也无论后续客户端是否宕机,也无论后续网络是否正常,服务器只要等待 lease 超时,就可以保证对应的客户端节点不会再继续 cache 数据,从而可以放心的修改数据而不会破坏 cache 的一致性。
优化点
优化点一:服务器在修改元数据时首先要阻塞所有新的读请求,造成没有读服务。这是为了防止发出新的 lease 从而引起不断有新客户端节点持有 lease 并缓存着数据,形成“活锁” 。优化的方法很简单,服务器在进入修改数据流程后,一旦收到读请求则只返回数据但不颁发 lease。从而造成在修改流程执行的过程中,客户端可以读到元数据,只是不能缓存元数据。进一步的优化是,当进入修改流程,服务器颁发的lease 有效期限选择为已发出的 lease 的最大有效期限。这样做,客户端可以继续在服务器进入修改流程后继续缓存元数据,但服务器的等待所有 lease 过期的时间也不会因为颁发新的 lease 而不断延长。实际使用中,第一层优化就足够了,因为等待 lease 超时的时间会被“优化点二”中的优化方法大大减少。
优化点二:服务器在修改元数据时需要等待所有的 lease 过期超时,从而造成修改元数据的操作时延大大增大。优化的方法是,在等待所有的 lease 过期的过程中,服务器主动通知各个持有lease 的节点放弃 lease 并清除 cache 中的数据,如果服务器收到客户端返回的确认放弃 lease 的消息,则服务器不需要在等待该 lease 超时。该过程中,如果因为异常造成服务器通知失败或者客户端节点发送应答消息失败,服务器只需依照原本的流程等待 lease 超时即可,而不会影响协议的正确性。
下一节Lease的更高级使用