Cassandra有一个非常重要的特性,叫做Tunable Consistency。当RW>N时保证副本保持strong consistency,当RW=< N时系统的所有副本保持最终一致性。(关于这个特性可以参看< Cassandra的副本策略>这个文章)
在Cassandra的文档中,有这样的一段话:
You can tune Cassandra’s consistency level per-operation, or set it globally for a cluster or datacenter. You can vary the consistency for individual read or write operations so that the data returned is more or less consistent, as required by the client application. This allows you to make Cassandra act more like a CP (consistent and partition tolerant) or AP (highly available and partition tolerant) system according to the CAP theorem, depending on the application requirements.
这段话描述了通过调整consistency level可以让cassandra系统更像(act more like)一个CP或者一个AP系统。从表面上看,这个段文字,和我最开始说的结论”当RW>N时保证副本保持strong consistency,当RW=< N时系统是最终一致性”是相同的。其实不然。调整consistency level不能让cassandra更像CP和AP。也就是说”副本保持strong consistency”不等于CP,”所有副本保持最终一致性”不等于AP。
要说明这个问题,就要从CAP定理说起。
CAP定理说分布式系统不能同时满足以下3个属性:
- Consistency: 这里是指linearizability Consistency。
- Availability:是指每个请求被发送到一个没有宕掉的机器上,都能被成功的完成。
- Partition tolerance:是指网络分区是可以发生的,系统可以容忍网络分区。
(关于CAP定理是什么可以参看<从Paxos不违反CAP来解释什么是CAP定理>)
CAP定理中Consistency实际上是指Linearizability,也可以叫做Linearizability Consistency。那么什么是Linearizability Consistency那?Linearizability Consistency也叫原子一致性,系统具有线性一致性后,当client将数据是原子写入的系统中的,只要一个value被写入,那么后续的client做read操作时,一定能够读到这个新值。这里要注意的是,这里的Linearizability Consistency讲的是客户端视角。而Cassandra的consistency level影响的是服务端的副本的一致性,是一个服务端视角。
(关于什么Linearizability,以及Linearizability的作用请参考<线性一致性(Linearizability)是并发控制的基础>这篇文章)
服务端的副本一致性与客户端的linearizability Consistency,是有关联的,但不是相同的特性。那么我们通过consistency level把副本的一致性调整为强一致性,在客户端视角上系统是否会变成Linearizability Consistency那?答案是不是的。
要解释为什么当RW>N时,Cassandra不是Linearizability Consistency,我们首先要说明,每个写入操作,都会分配一个非全局的本地的时间戳给这个写入操作。当2个client同时写入一个cell时,是通过Last Write Win来解决写入冲突的,也就是时间戳大的写入操作会覆盖时间戳小的写入操作。由于时间不是完全同步的,RW>N只能保证,一个值成功写入后在没有后续写入的情况下能够读取出来。但是由于时间不完全不同,所以在RW>N的情况下仍然能够出现,后发起的请求(带着更早的时间戳)被先发起的请求(带着更新的时间戳)所覆盖。这就不能保证Linearizability Consistency里面要求的,后发起的写入请求,一定能被后续的读请求所读到。