consul馆提供session机制,可用于构建分布式锁。 session作为节点,健康检查和key/value数据之间的绑定层。 它们旨在提供粒度锁定,并受到“The Chubby Lock Service for Loosely-Coupled Distributed Systems的极大启发。
Session Design
consulsession代表了具有非常具体语义的contract。 当构建session时,可以提供节点名称,健康检查列表,行为,TTL和lock-delay
。 新建的session中提供了一个可以用来识别它的命名ID。 该ID可与KV存储一起使用以获取锁定:相互排斥的咨询机制。
以下是显示这些组件之间关系的图表:
consul提供的contract是,在下列任何一种情况下,session将被invalidated :
- 节点被注销
- 任何健康检查都被注销
- 任何健康检查都进入危急状态
- session被明确地销毁
- 如果适用,TTL过期
session invalidated时,会被破坏,无法再使用。 关联的锁会发生什么事情取决于创建时指定的行为。 Consul支持release
和delete
行为。 如果没有指定,则release
行为是默认的。
如果正在使用release
行为,与session相关联的任何锁将被释放,并且键的ModifyIndex
将递增。 或者,如果使用delete
行为,则与任何所保持的锁相对应的键被简单地删除。 这可以用于创建由consul自动删除的临时条目。
虽然这是一个简单的设计,它可以实现多种使用模式。 默认情况下,使用gossip based failure detector作为相关的健康检查。 该故障检测器允许Consul检测持有锁的节点何时发生故障并自动释放锁。 这种能力为consul锁提供了活力 ;
那就是在失败的情况下,系统可以继续取得进展。 然而,由于没有完美的故障检测器,因此即使锁所有者仍然存在,也可能存在一个假阳性(检测到故障),导致锁释放。 这意味着我们正在牺牲一些安全 。
相反,可以创建一个没有关联的健康检查的session。 这消除了对于安全性的假阳性和交易活动的可能性。 即使现有的所有者失败,您也可以绝对地确定consul不会释放锁定。 由于consulAPI允许强制破坏session,因此允许构建系统,
要求操作员在发生故障的情况下进行干预,同时排除split-brain的可能性。
第三个健康检查机制是sessionTTL。 创建session时,可以指定TTL。 如果TTL间隔到期而不更新,则session已过期,并且触发invalidated。 这种类型的故障检测器也称为心跳失效检测器。 它比基于gossip的故障检测器的可扩展性更低,因为它对服务器造成了更大的负担,
但在某些情况下可能适用。 TTL的contract是它代表invalidated的下限; 也就是说,在达到TTL之前,consul不会过期session,但允许延迟超过TTL的期限。 在session创建,session更新和领导者故障转移时,更新TTL。 当使用TTL时,客户端应该意识到时钟偏移问题:
即时间可能不会像在consul服务器上那样在客户端上以相同的速率进展。 最好设置保守的TTL值,并在TTL之前更新以考虑网络延迟和时间偏移。
最后的细微差别是session可能会提供lock-delay
。 这是0到60秒之间的持续时间。 当发生sessioninvalidated时,Consul防止在lock-delay
时间间隔内重新获取先前保存的任何锁; 这是Google Chubby的灵感来源。 这种延迟的目的是允许潜在的活着的领导者检测到invalidated,
并停止可能导致不一致状态的处理请求。 虽然不是一个防弹方法,但它确实避免了将睡眠状态引入到应用程序逻辑中,并且可以帮助减轻许多问题。 默认情况下是使用15秒延迟,客户端可以通过提供零延迟值来禁用此机制。
K/V Integration
KV存储和session之间的集成是session使用的主要场所。 session必须在使用前创建,然后由其ID引用。
扩展KV API以支持acquire
和release
操作。 acquire
操作的作用类似于Check-And-Set操作,只有当没有现有的锁定保持器(当前的锁定保持器可以重新acquire
,见下文)时,它才能成功。 成功时,有一个正常的key更新,但是LockIndex
也有一个增量,并且Session
值被更新以反映持有该锁的session。
如果在acquire
期间锁已经被给定的session保持,则LockIndex
不会递增,但key内容将被更新。 这使得当前的锁持有人更新key内容,而不必放弃锁并重新获取它。
一旦保持,可以使用相应的release
操作释放锁,从而提供相同的session。 同样,这样做就像一个Check-And-Set操作,因为如果给定invalidatedsession,请求将失败。 一个关键的注意事项是锁可以被释放,而不是session的创建者。 这是设计,因为它允许操作员干预和强制终止一个session,如果必要的话。 如上所述,sessioninvalidated还将导致所有持有的锁被释放或删除。 当锁释放时, LockIndex
不会改变; 但是, Session
被清除,并且ModifyIndex
递增。
这些语义(从Chubby大量借用)允许(Key,LockIndex,Session)的元组作为一个独特的“顺控程序”。 该定sequencer
器可以传递,并用于验证请求是否属于当前的锁持有者。 因为LockIndex
在每次acquire
递增,即使相同的session重新获取锁定,定sequencer
也可以检测到一个陈旧的请求。 类似地,如果session被invalidated,则与给定的LockIndex
对应的session将为空。
要清楚,这个锁定系统是纯粹的咨询 。 没有执行客户端必须获取锁来执行任何操作。 任何客户端都可以读取,写入和删除key,而不拥有相应的锁。 consul不是为了防止不良行为客户的目标。