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支持releasedelete行为。 如果没有指定,则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以支持acquirerelease操作。 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不是为了防止不良行为客户的目标。