Cassandra中的强一致性

8
根据DataStax文章所述,若 R+W > N,则可以保证强一致性。其中,R代表读操作的一致性级别,W代表写操作的一致性级别,N代表副本数量。
这里的"强一致性"是什么意思?它是否意味着每次从数据库返回查询响应时,响应始终是最新的值?如果在Cassandra中维护了强一致性的条件,那么是否存在数据返回不一致的情况?简而言之,强一致性是否意味着100%的一致性?
编辑1:添加了一些关于即使R+W>RF时Cassandra可能不一致的情况的额外材料。
  1. 使用Quorum CL时写入失败
  2. Cassandra的最终一致性
5个回答

4
卡桑德拉有可调的一致性,你可以选择一些权衡。R + W > N - 这只是意味着在你的往返旅行中必须有一个重叠节点,该节点具有实际和最新的数据以保持一致。例如,如果你在 CL.ONE 写入,则需要在 CL.ALL 读取才能确保获得一致的结果:N+1 > N - 但是你可能不想要 CL.ALL,因为你的集群中无法容忍单个节点故障。
通常情况下,你可以在读取和写入时选择 CL.QUORUM 以确保一致性并容忍节点故障。例如,在 RF=3 的情况下,QUORUM 需要 (3/2)+1=2 个节点可用,因此 R+W>N 将为 4>3 - 你的请求是一致的,并且你可以容忍单个节点故障。
需要记住的一件事是 - 在所有节点(卡桑德拉和应用程序)上具有密切同步的时钟非常重要,你将需要运行 ntp。

RF是什么意思? - DarkSkull
@DarkSkull RF == 复制因子 - Aaron

2

对于读和写操作,ANY、ONE、TWO和THREE的一致性级别被认为是弱一致性,而QUORUM和ALL则被认为是强一致性。


2
尽管这是一个旧问题,但我想插一句话以澄清记录。
R+W>RF并不意味着强一致性。
一个R+W>RF的系统只能最终达成一致。强一致性保证在节点故障或写入之间会中断。例如,考虑以下场景:
假设有三个节点A、B、C,RF=3,W=3,R=2(因此,R+W = 5 > 3 = RF)
进一步假设k键与v值相关联,即(k,v)存储在数据库中。假设发生以下一系列的动作:
t=1:用户向A、B、C发送(k,v1)写请求;
t=2:(k,v1)到达A并被写入A的存储器中;
t=3:读者1发送关于键k的读请求,并得到A和B的回复;
t=4:读者1接收到(k,v1)的响应,因为是最新的写入,按最新获胜规则;
t=5:读者1发送另一个读请求,由B和C响应;
t=6:读者1接收到一个较旧的值(k,v)。不一致。
t=7:(k,v1)到达C并被写入C的存储器中;
t=8:(k,v1)到达B并被写入B的存储器中;
这证明了W+R>RF无法保证强一致性。为了确保强一致性,您可能需要使用另一种算法,比如Paxos或Raft,以确保写入是原子的。
您可以在这里(请查看FAQ部分)阅读有趣的文章。
编辑:
Cassandra确实有一些内部机制(称为阻塞读修复),可以在向客户端返回响应之前触发同步写操作。这种同步读修复发生在查询节点之间存在不一致性以实现读一致性级别的情况下,并确保某些已知的单调读一致性(请参见以下定义)。这使得上面示例中(k,v1)在第一个读请求的响应返回之前被写入节点B,所以第二个读请求也将有一个更新的值。(感谢@Nadav Har'El指出这一点)
然而,这仍然不能保证强一致性。以下是一些清晰其内容的定义: 顺序/强一致性:任何执行的结果都与按某种顺序发生读写并按其程序指定的顺序在每个单独处理器中出现的操作相同[由Leslie Lamport定义]。

单调读一致性:一旦您读取了一个值,所有后续读取将返回此值或更新版本。

顺序一致性要求客户端程序/读者在程序指令序列中执行写入语句之前看到最新的写入值。


2
你错了。你期望的“一致性”被称为“单调读取”(即在已经读取新值之后从不读取旧值),而Cassandra实际上支持它!在t=3步骤中,当协调器从A和B接收到并且发现它们是不同的时,它会进行调和(生成要在t=4中返回的结果),但也会将调和后的结果同步发送到A和B两个节点(读取完成前不会返回)。因此,当读取完成并返回数据(k,v1)时,这些数据位于A和B上。无论选择哪两个节点执行下一个读取,都将返回(k,v1)。 - Nadav Har'El
2
Cassandra有两个不同的特性。其中一个是概率性读修复,在达到CL后有时会在后台运行。另一个是协调器在达到CL之前从不同的副本接收到不同的数据时发生的协调。然后,Cassandra将协调后的数据写回,并等待写入完成。关于多DC(Cassandra不会等待其他DC上的写入)和CL(写入应该具有哪个CL?)存在细微问题,但他们并没有简单地忘记处理这个问题。https://issues.apache.org/jira/browse/CASSANDRA-2494 - Nadav Har'El
1
@NadavHar'El 谢谢。阅读 CL 作为 Quorum 将意味着需要写入 quorum 的 CL 以实现一致性,是吗?此外,如果跨 DC 的读修复不同步,这是否意味着一致性保证在这里被破坏了? - Prakhar Agrawal
1
虽然我在某种程度上是Cassandra专家(参与了将其重写为C ++,即ScyllaDB),但我不记得每个细节,您可能需要询问更大的专家或检查代码。如果我没记错,协调等待LOCAL_QUORUM写入成功,而不管读取CL,这对于QUORUM写入已足够好。是的,如果我没记错,跨数据中心的读取单调性是有问题的。它不必是这样,这只是为避免非常高的延迟而采取的捷径... - Nadav Har'El
1
@NadavHar'El,感谢您的快速回复。是的,读取与写入同时发生。R+W > RF,这表明我们具有强一致性。但是,同一个读取者在看到新值之前可能会看到旧值。 “等待直到所有三个节点上的写入成功” - 系统是否还会阻止读取者在所有三个节点完成之前看到新值? - undefined
显示剩余11条评论

1

是的。如果R + W一致性大于副本数,则始终可以获得一致的数据。100%的一致性。但为了实现更高的一致性,您必须牺牲可用性。

Cassandra具有可调整一致性的概念(在查询基础上设置一致性)。


1
https://dev59.com/G4zda4cB1Zd3GeqPiiaX 接受的答案指出,即使在R+W>N的情况下,也无法提供强一致性。除了满足R+W>N条件之外,是否还需要进行某种调优才能实现强一致性? - Farsan Rashid
我找到了另一篇文章,其中强调了一种情况,即使R+W>RF(@FarsanRashid给出的链接中的第二个答案也强调了其中的一个情况),也会返回不一致的数据。https://blog.scottlogic.com/2017/10/06/cassandra-eventual-consistency.html - Vishal Sharma
R+W不能保证强一致性。 - manpreet singh
1
@manpreetsingh https://cassandra.apache.org/doc/latest/architecture/dynamo.html#picking-consistency-levels - undefined_variable

1
我实际上把这个“Strong Consistency”称为“强一致性”。它是会话级别的,也就是单调读一致性(参见@NadavHar'El的回答)。
但它不是顺序一致性,因为Cassandra并不完全支持锁定、事务或序列化写操作。只有轻量级事务,支持写操作的本地序列化和读操作的序列化。
为了让事情容易理解,假设我们有三个节点 - A、B、C,并将读取配额设置为3,写入配额设置为1。
如果只有一个客户端,它会写入任何一个节点 - A。 B和C可能不同步。(最终他们会--最终一致性)
但当客户端再次读取时,需要客户端获取至少三个节点的响应,并通过比较最新时间戳来使用A的记录。这就是单调读一致性。
然而,如果有两个客户端尝试同时更新记录,或者如果他们尝试同时读取值并重写它(例如将列增加100): 客户端C1和客户端C2都将当前列值读取为10,然后决定将其增加100: 虽然C1只需要向一个节点写入110,但客户端C2也会执行相同的操作,任何节点上的最终结果只能达到110的最大值。
然后我们在这些操作中丢失了100(丢失更新)。这是由竞争条件或并发问题引起的问题。必须通过序列化操作并使用任何形式的锁来解决,就像其他SQL数据库实现事务一样。
我知道Cassandra现在有新的计数器列,可能可以解决这个问题,但它在完整事务方面仍然受到限制。而且Cassandra也不应该成为事务性数据库,因为它是牺牲一致性以换取可用性的NoSQL数据库。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接