分布式系统之Lease机制
是什么
Lease(意为约定、承诺)机制是分布式系统中的一个非常重要的机制,用于确保数据或状态的一致性,它应用非常广泛,是Paxos等一致性算法的基础之一。
(虽可借助Paxos、Raft等算法来实现数据一致性,但Lease机制是这些算法的原理之一,是更细粒度的“牛刀”)。
核心思想
承诺方向被承诺方承诺在一定时间内坚守某种约定。这里的时长即承诺的有效期,Lease的有效期;承诺的内容是多样的,可以是数据的状态、某种授权等,常见的承诺:
lease 这段时间内,我们不更新数据
lease 这段时间内,我们不会选别人(比如 paxos)
lease 这段时间内,我不kill 你
详见下面例子。
例子
基于Lease机制的数据缓存系统
问题:如何防止客户端缓存的数据和服务的的数据不一致。
思想:服务端承诺发给客户端的数据在一段时间内不会被修改(从而也即这段时间内服务端和客户端数据是一致的),这样客户端就可以缓存该数据,从而在这段时间内不用请求服务端了。
具体:假设服务端数据为key-value存储。
当有客户端向服务端读/写某个数据(假设为k1-v1)成功时,服务端返回v1以及时长为T的lease;
在接下来的T时间内,一方面,该客户端就可以缓存并使用k1-v1数据而不用向服务端请求了;另一方面,服务端就不会执行其他客户端的写k1操作了,而是以sleep等方式等到k1的lease时间结束才执行写入。
基于Lease机制的节点状态确定的全局一致性
问题
分布式系统中确定一个节点是否处于正常工作状态是一个困难的问题,由于可能存在网络故障,节点的状态是无法通过网络通信来确定的。
例如对于监控节点Arbiter和副本节点A、B、C,若Arbiter只通过心跳判断A、B、C节点是否正常则会有问题:可能因为网络问题导致Arbiter认为A挂了但实际上A是正常的,此时Arbiter和A对A状态的认知出现了分歧;更甚,若A是主节点则Arbiter在认为A挂了后会选出新的主节点从而存在双主的问题(brain split,脑裂问题)。它们本质上都是节点状态的确定问题。
故,如何确保对节点状态的认知是全局一致的?
思想:Arbiter收到节点A心跳后同时返回一个Lease给A,承诺在Lease有效期内认为A是正常的(即使有网络问题);对于双主问题,Arbiter对于选出的主节点同时返回一个特殊的Lease,表示在Lease有效期内承诺只认该节点为主节点而不会选其他节点。
Lease时长的设置
相对时长:
Lease机制中承诺方和被承诺方都需要知道承诺的时长,通常后者是从前者返回数据中知道时长的,因此两者的时长一致,这也是理想情况。
然而现实中系统时钟差异、数据返回的网络延迟等原因可能造成两者的有效时长并不一致,此时会有问题,几种情况:
1、承诺方的Lease有效期比被承诺方的长(例如前者时钟比后者慢):结果是后者认为Lease过期了但前者仍在遵守承诺(例如客户端认为缓存数据失效了但服务端仍在保证k1数据不被其他人更新),这种场景不会有正确性的问题,顶多是被承诺者更频繁地来申请新lease。
2、与上面相反,前者比后者短:这种场景有正确性问题——结果是前者认为Lease过期了从而不再遵守承诺了(例如允许其他人更新k1数据)但后者认为Lease还有效(例如还用着缓存数据),这样就无法保证数据一致了。
综上,实践中通常承诺者的Lease时长设置得比被承诺者的长一些。
单方时长:
对承诺者或被承诺者单方面来说:Lease时长太长则承诺太不容易过期,可能导致系统不可用问题(因承诺期内不允许某个数据变更);太短则承诺太容易过期,造成系统抖动频繁。
实践中通常设置10s级别的Lease时长,经验值。
参考资料