尽管这是一个旧问题,但我想插一句话以澄清记录。
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定义]。
单调读一致性:一旦您读取了一个值,所有后续读取将返回此值或更新版本。
顺序一致性要求客户端程序/读者在程序指令序列中执行写入语句之前看到最新的写入值。