问题背景

在旧的分布式框架下,所有节点共同在一个共识组内(Meta组),因此需要全局执行的操作可以在共识组内执行保证最终一致性,即每个节点最终能够执行到该操作。

但在新的架构里,考虑到随着节点数目增多后,Meta组的存在会极大影响性能,且Meta组的leader的任务量会非常大,甚至成为系统瓶颈,因此我们删除了Meta组,由

几个ConfigNode组成的共识组来管理整个集群的DataNode。但这会带来的问题是,我们需要考虑如果保证全局执行的操作的原子性。

以删除存储组为例,该操作需要发送给所有DataNode进行执行,清空本地的数据,元数据,以及对应的分区表和元数据缓存。

由于IoTDB目前单机和分布式都不支持事务处理,如何保证所有节点都成功执行了该操作,我们给出了以下几种方案。

解决方案

用户重试

最简单的方式是ConfigNode发送给所有节点后,在一个timeout时间内,如果有节点未返回Success,则返回给用户partial success信息,让用户自行重试。

自动重试

ConfigNode在某个节点timeout后,自动重试。

自动重试方案流程(以删除存储组为例):

  • Coordinator将DeleteStorageGroup请求转发给ConfigNode共识组
  • 日志在共识组内进行共识,共识完成后返回给用户开始删除的信息
  •  apply该日志时进入第一阶段:
    • 所有ConfigNode为所有DataNode维护一个状态,用于删除存储组
    • 共识组Leader中的异步线程检测到状态创建完成,开始向所有DataNode发起删除存储组请求
    • 在transfer leader后,新leader上的异步线程生效,继续发送删除存储组的请求(该操作具有幂等性)
  • 在删除完成后,leader在组内发起DeleteStorageGroup完成的日志,所有节点删除对应状态

Lease机制

Lease机制最初用来解决分布式存储中缓存一致性的问题,用来保证缓存的强一致性。Lease由颁发者授予的在某一有效期内的承诺,颁发者一旦发出lease,无论接收方是否收到,无论接收方处于何种状态,只要lease未过期,颁发者都认为lease生效。对于接收方来说,lease过期后,不能再使用该承诺。

Lease 机制的基本原理如下:中心服务器在向各节点发送数据时同时颁发一个 lease,每个 lease 具有一个有效期,,一旦真实时间超过这个时间点,则 lease 过期失效(假设中心服务器与各节点的时钟是同步的)。通常情况下,中心服务器的lease过期时间要略长于节点上的lease过期时间,这样在一定程度上减轻了时钟误差带来的问题。(假设Clock drift在一定范围内)

该机制的具体表现为:

  • 如果接收方需要进行写操作,则向中心节点发送一个lease request,拿到对应的lease之后才可以执行写操作
  • 中心节点等待所有lease超时再进行写入,这里有一个优化方案是,server直接给其他节点发送invalid lease,这样可以不需要超时等待时间

在IoTDB中,引入lease机制的作用是在DataNode脱离ConfigNode控制时(网络分区,full GC等),阻塞DataNode上的读写操作。

例如,在删除存储组时,需要ConfigNode向所有DataNode发送删除存储组的请求,此时可以设置该请求的timeout时间大于lease过期时间,这样保证若ConfigNode和DataNode网络分区时,请求timeout时,DataNode上的lease

必定过期,因此用户无法在该DataNode上执行读写,以防读到脏数据,或者写入已被删除的存储组。在DataNode可以重新与ConfigNode建立连接时,申请lease,并且接收到之前的删除存储组操作。

引入lease机制会使得系统的复杂度增加,但作为成熟的分布式的协议,并且在工业界下已经被大量使用的方案,如果有需要,可以在后续引入IoTDB中。


工程中的应用:

  • GFS 中的 Lease。GFS 中使用 Lease 确定 Chuck 的 Primary 副本。Lease 由 Master 节点颁发给 primary 副本,持有Lease 的副本成为 primary 副本。
  • Chubby通过paxos协议实现去中心化选择primary节点,Secondary节点向 primary节点发送 lease,该 lease 的含义是: “承诺在 lease 时间内,不选举其他节点成为 primary节点。除此之外,Chubby用lease维护缓存一致性,client只有拥有primary颁发的lease才可以进行读写操作。
  • Zookeeper 中,集群中在选择一个leader节点后,其余节点成为follower,follower接收leader颁发的租约后可进行读操作。当有写操作时,leader将writing replicate到follower时,follower会将租约失效,commit后重新申请,因此zookeeper的写入性能不会太高。

  

参考文献

An Efficient Fault-Tolerant Mechanism for Distributed File Cache Consistency

  • No labels