gaodq /var/log/message

各种“一致性”

Consistency,一致性这个词经常见到,并且还是在不同的场景下有些不同的含义,在这把我见到的一些总结一下。

一致性模型

一致性并不是一种性质,更合理的应该看做是一组不同要求的模型,也就是常说的一致性模型。一个模型给定一组规则规定相关的操作导致的状态转化,如果一个系统的操作历史在任何情况下都符合这个规则,那我们认为这个系统是符合这个一致性模型的。

为了满足不同性能以及一致性的需求,人们提出了多种一致性模型,从强到弱(就是对于并发读写顺序规定的严格性)分别有linearizability, sequential consistency, causal consistency 和 PRAM等等,同时后者的性能也依次比前者高。

这些不同的一致性模型大都是在研究多核CPU并发时对于内存的访问时提出的,当然也适用于分布式系统。在分布式存储中所提到的满足一致性一般指副本数据满足线性一致性(linearizability),不过说不满足一致性的一般都会满足最终一致性,否则副本就没啥意义了。

一致性(共识)算法

一致性算法就是人们常提到的Paxos、Multi-Paxos、Raft等等,实际上这些算法是共识(consensus)算法,就是多个节点对某一提案达成共识的算法,并且在论文中也是只有consensus,并没有提到consistency。只是因为通常使用这些共识算法来实现容错复制状态机,维持不同副本间日志的一致,所以习惯称之为一致性算法。

副本一致性

在分布式存储系统中都会维持多分副本来提高数据可靠性,这就带来了副本间数据的一致性问题,通常所说的一致性大都是指在这里的一致性问题。

在研究这个问题常用的网络模型和故障模型下,副本间的网络数据可能会无限延迟、重复到达,而副本节点也可能发生重启或故障。一个系统的一致性问题一般表现为客户端访问多个副本数据的一致性问题。

先看什么是副本的一致性,一般说一个系统是强一致的就是说客户端访问数据表现为线性一致,就是写入了一个值之后肯定能读出来,读取一个值之后再读这个值如果中间没有修改过两次读的值一定相同。

再看如何实现,比较容易想到的做法就是写和读时都访问所有副本,但这样带来的问题就是延迟太大,故障恢复太慢太复杂。再者就是单master读写,由master向slave复制数据,这样正常情况下是能保持线性一致的。但是一旦master死掉,那就需要选一个新的与master数据一致的slave来负责,而且这里为了保证不出现多个master,需要另一个一致性系统来选。还有方法就是直接在副本间使用共识算法来保证数据一致。所以在这里如何保持副本间的一致性就转化为了使用共识算法的问题。

前面说的master向slave同步,如果是异步复制,在master发生故障选择新的slave提升为master时很有可能新的master缺少部分数据,从而损失了一致性,所以在这里需要权衡性能和数据可靠性需求,选择不同的同步复制slave个数来实现不同的可靠性。

所以对于副本一致性的解决,要么采用共识算法,要么采用master-slave方式,同时需要master-slave间同步复制以及需要一个共识系统选master。

最终一致性

最终一致性也是讲的是副本间数据同步的最终一致,在”一段时间”内所有副本达到一致状态,但是一段时间并没有规定多久,当然也很有可能是”永远”。最终一致是个比较模糊的概念,当单master的系统正常工作时,对外表现的是线性一致,但在master崩溃且一个并没有与master数据一致的slave被选为了新master,那这时系统该不该说是最终一致的呢。

CAP

这里的一致性指的也应该是副本数据对于客户端的线性一致性表现。在发生网络或节点故障恢复后系统对于用户表现的数据是否线性一致。

ACID

这里的consistency是在事务中的概念,这里更多的是应用方面的概念,不是由数据库层面来保证的。应用应该利用数据库的Atomic及Isolation性质来保证自己数据的一致性。

参考

  1. Strong consistency models
  2. 《Designing Data-Intensive Applications》
  3. 分布式系统一致性的发展历史 (一)
  4. 分布式系统一致性的发展历史 (二)