顺序一致性和线程一致性

作者: Jiafu | 来源:发表于2020-01-21 18:28 被阅读0次
    顺序一致性(Sequence Consistency)

    顺序一致性指的是,同一个处理器上的不同操作(operation),是按程序顺序(program order)来进行的。但是对于不同处理器上的操作,是没有保证的。

    线性一致性(Linearizability)

    线性一致性指的是,对于不同处理器上的任意操作A、B。如果A的完成时间小于B的开始时间,那么B一定可以看到A的结果。

    如何实现线性一致性

    共识算法,比如raft。有3种方案:

    1. 可以让所有请求(读写)都用走一遍Log replication。
    2. ReadIndex:读请求到leader后,leader记下当前committed index为readIndex。然后leader向follwer发起心跳,以保证当前自己还是leader。然后等到leader的Apply index达到committed index之后,就可以处理读请求,响应客户端了。要保证读的线性一致性,其实就是保证读请求一定可以读到当前最新的数据。具体的说,假设读请求发起的时间点是t1,那么满足线性一致性就是保证读请求可以返回所有在t1时间点之前就完成的写操作结果。通过记录ReadIndex并且和apply index,可以保证读请求读到了当前节点上的最新数据。那么为什么要加leader校验呢?我们可以考虑如果不加leader校验会出现什么场景。首先leader可能已经发生切换,有了新的leader,并且有了新数据,但是旧leader还没有感知到。客户端C1发起读请求到新leader,拿到新数据。然后客户端C2发起读请求到旧leader,由于没有leader确认这一个步骤,那么旧leader可能会返回旧数据。这样C1已经看到新数据的情况下,C2后发起的读请求看到旧数据了,这违背了线性一致性。
    3. 虽然 ReadIndex Read比第一种方法快很多,但我们发现还是有一次心跳包的网络开销,raft论文里提到了一种更激进的方式,也就是leader其实都存在一个'在为期', 也就是说leader会向follower发送心跳包,当收到大多数节点的回复后即确认了leader身份,并记录下时间戳t1,如果读过raft论文我们会知道,follower会在Election Timeout超时后,才会认为leader挂掉,并发起一次新的选举,也就是说在下一次leader选举肯定发生在t1 + Election Timeout +/- 时钟偏移量之后,因此第二种方法的中,通过发送心跳包确认leader身份这一步就可以省略掉了,在Election Timeout内只需要确认一次即可,相对一种方式,不仅仅不需要写raft日志,连心跳包都省略掉了,可想而知,性能会大大提升,但这里存在一个潜在的问题是,服务器的时间可能会偏移,存在一定的误差,如果偏移过大的话,这种机制就不够安全。
    ZooKeeper的一致性保证

    当ZooKeeper只有写操作的时候,ZooKeeper满足线性一致性。
    当ZooKeeper有读写操作的时候,ZooKeeper满足顺序一致性。比如说对于同一个客户端发起的各种读写请求,客户端可以认为是按发起顺序来完成的(中间不可以有失败重连)。

    参考资料

    线性一致性vs顺序一致性

    线性一致性和 Raft

    相关文章

      网友评论

        本文标题:顺序一致性和线程一致性

        本文链接:https://www.haomeiwen.com/subject/bcwezctx.html