Skip to content
This repository has been archived by the owner on Jun 12, 2023. It is now read-only.

cap in tns

jerry edited this page May 2, 2017 · 14 revisions

cap

C:一致性 A:可用性 P:分区容忍性

Architecture in tns

集群采用无中心化设计,按节点ID排序并顺时针组成一个环,如图C1,节点按固定频率将其知道的cluster list、cluster node status和service list同步给下一个节点,并记录被同步节点的健康状态。

C1

故障检测

tns采用增量故障检测算法来检测集群故障。

C2

一个Up节点单次故障不会被立即标记为Down,而是被标记为Down_1,如果Down_1节点下次检测仍是故障,则会被标记为Down_2,如果Down_2节点下次检测仍是故障,则会被标记为Down,此后不会在对该节点执行故障检测。如下图:

Cluster 状态机

一致性

cluster视角

在tns中,不可变约束包括cluster node列表、cluster node健康状态、service node 列表。

tns 针对以上不可变约束满足最终一致性

增加node(cluster、service)

假设数据同步周期为T,在某个cluster node上操作增加一个node(cluster、service),在最长同步周期(T)后数据会被同步到下个节点,以此类推,假设集群节点数为N,最终一致时间最长为(N-1)T

移除node(service)

tns目前只支持移除service node,对于cluster node的移除功能暂不支持。

Service 状态机

对于移除service node,cluster 需要经历四个阶段:Leaving、Tombstone_1、Tombstone、Remove

其中Tombstone_1、Tombstone、Remove阶段由后台任务周期执行触发

  • Leaving阶段

    • 被移除的service node会被立即变更状态为Leaving,并取消对应的ping任务
    • 在周期T内,状态会被传输到下个节点
    • 最终在(N-1)T内,状态会被传输到所有节点
  • Tombstone_1阶段

    • 检查service node状态
      • 若状态为Leaving,且已停留了足够长时间,将状态变更为Tombstone_1
  • Tombstone阶段

    • 检查service node状态
      • 若状态为Tombstone_1,且已停留了足够长时间,将状态变更为Tombstone
  • Remove阶段

    • 检查service node状态
      • 若状态为Tombstone,且已停留了足够长时间,直接移除
  • 处于Leaving状态的节点仍会同步给其它节点;处于Tombstone_1、Tombstone状态的节点不会同步给其它节点;这三种状态均不接受状态更新;

为什么这么设计?

保证Leaving状态广播到整个集群;保证在真正移除前,集群所有节点处于Tombstone_1或Tombstone状态(保证移除后,该service node不会再被同步回来)。

假设处于Leaving状态的service node,未能广播给整个集群,会出现部分cluster node执行了移除操作,最终导致移除后被那些没能收到Leaving请求的节点将数据又同步回来,导致下线service node失败;另外,处于Tombstone状态的service node,节点一旦被执行移除,其上一个节点待移除数据可能处于Leaving甚至是UP状态,数据可能会被同步回来,最终导致集群出现错误,所以必须保证,在集群某节点在执行真正移除前,其余节点至少处于Tombstone_1或Tombstone状态。

详细推导过程见一致性详解

client视角

目前版本客户端不考虑一致性问题,未来可能会增加单调读一致性,但需求不大

tns-client会定时从cluster同步数据,在这个周期内,可能会出现数据不一致。例如某时刻一个service node被移除或已经down 掉,并未及时被tns-client同步过来,可能会导致client使用一个错误的service node来执行业务,出现错误,在tns-client中提供了brokenNode接口来主动移除故障节点

可用性

cluster视角

tns中,集群节点数量N>0即可写。

client视角

tns中,集群节点数量N>0即可读,同时因为tns是一个最终一致性的系统,节点的down机,会在(N-1)T内广播到整个集群,同时tns-client定时从某个cluster node同步数据也是定时操作,所以同步时某个节点可能不可用,此种情况可以采取两种措施:

  1. 换个节点立即重试
  2. 等待下一个同步周期(选择到一个健康节点)

目前tns-client采用方法2

分区容忍性

一般认为在同一个机房不会出现分区,在跨机房场景中会出现分区现象;同时在同机房内节点的上下线也被认为是特殊的分区。如图C3: C3

tns不满足跨机房的分区容忍性,如果跨机房部署,出现分区情况,在没有人为增加、移除节点的情况下没有问题(tns中节点的增加、移除操作均为人工操作),所以这样部署问题也不大,只要在操作前检查下集群状态即可,操作后检查下结果是否已经被广播到整个集群。

一致性详解

cluster中有三个关键时间或周期

  1. cluster间同步数据的周期 T1
  2. service节点Leaving、Tombstone_1、Tombstone状态保留最短时间 T2
  3. 后台执行service node移除的周期 T3

cluster 之移除service node

前文已经介绍,下线一个service node需要处理好如下两件事情:

保证Leaving状态广播到整个集群; 保证在真正移除前,集群所有节点处于Tombstone_1或Tombstone状态(保证移除后,该service node不会再被同步回来

接下来看看三个周期需要满足什么条件?

若要保证Leaving状态广播到整个集群,只需保证每个节点都能将Leaving状态同步给下个节点,即在Leaving状态被转换成Tombstone_1前,至少发生过一次同步操作,推导出 T2 > T1

若要保证真正移除前,集群所有节点处于Tombstone_1、或Tombstone状态,只需保证,集群最早执行移除操作的时间 (TR) > 集群最晚将节点状态转成Tombstone_1的时间 (TT)

根据集群最终一致性性质,不难推算出,集群最晚收到Leaving的时间为 (N - 1)T1,从Leaving到Tombstone_1最长时间为 T2 + T3,所以 TT = (N - 1)T1 + T2 + T3

同理,TR = T2 + 2T3

进而可推算出:

TR > TT

=> T2 + 2T3 > (N - 1)T1 + T2 + T3

=> T3 > (N - 1)T1

综上,cluster三个周期需满足:

  • T2 > T1
  • T3 > (N - 1)T1

回过头来,假设没有Tombstone_1阶段是否可行?

根据上文推算过程,可得出

TT = (N - 1)T1 + T2 + T3

TR = T2 + T3

显然,无法满足 TR > TT,所以 Tombstone_1阶段是必要的

集群节点数上限

根据上边的推算,T3 > (N - 1)T1,目前T3 = 10分钟,T1 = 5秒,可得 N不能超过121,对于tns负载特点,120完全足够,一般三个节点即能满足大多数系统需求

最终一致时间

接下来看下集群最终一致时间到底要多长

提前须知

  • 对于增加节点(cluster、service),初始状态均为Joining,只有UP状态的节点才会同步给客户端
  • 对于增加cluster node,待增加的node状态只能被其上一个节点修改

增加cluster node

根据cluster 特性可知,一旦待添加的节点,被其上一个节点修改状态为UP,然后最终使集群达到最终一致(UP),需要时间 (N - 1)T1

那么待添加节点状态变为UP状态需要多长时间呢?

假如,操作的节点正好是待添加节点的上一个节点,那么由Joining - > UP ,至多需要T1时间,从而最终UP一致时间最长为:T1 + (N - 1)T1 = NT1

假如,操作的节点正好是待添加节点的下一个节点,那么由Joining - > UP ,至多需要NT1时间,从而最终UP一致时间最长为:NT1 + (N - 1)T1 = (2N - 1)T1

增加service node

根据cluster特性可知,Joining状态的service node同步到整个集群需要(N - 1)T1时间,然后Joining - > UP 由各自的cluster node负责ping检测,其中检测启动时间为Random( pingFrequency ),从而最终UP一致时间最长为:(N - 1)T1 + pingFrequency

下线service node

根据cluster特性可知,Leaving状态的service node同步到整个集群需要(N - 1)T1时间,一旦集群达到Leaving一致状态,客户端即获取不到该service node,所以对于客户端而言,最终一致时间最长为:(N - 1)T1