读取失败,一致性一

Read fail with consistency one

我有3个节点;数据中心 1 中的 2(节点 1 和节点 2)和数据中心 2 中的 1(节点 3)。复制策略:网络拓扑,dc1:2,dc2:1。

最初我关闭 dc1 中的一个节点(节点 2)并写入 100 000 个一致性为 2 的条目(通过 C++ 程序)。写完后,我关闭数据中心2(节点3)的节点,开启节点2。

现在,如果我尝试读取我写的那 100,000 个条目(再次通过 C++ 程序),并将一致性设置为“一”,我将无法读取所有这 100,000 个条目,即我能够读取只有一些条目。随着我一次又一次地运行程序,我的程序获取越来越多的条目。

我期待的是,由于 up 的 2 个节点中的一个包含所有 100 000 个条目,因此,当设置一致性为 ONE 时,读取程序应该在第一次执行时获取所有条目。

这跟读修复有关吗?我在想,因为读取修复是在后台进行的,这就是为什么节点无法响应所有查询的原因?但是我在任何地方都找不到有关此行为的任何信息。

Per documentation,读取时的一致性级别ONE

Returns a response from the closest replica, as determined by the snitch. By default, a read repair runs in the background to make the other replicas consistent. Provides the highest availability of all the levels if you can tolerate a comparatively high probability of stale data being read. The replicas contacted for reads may not always have the most recent write.

您是否检查过您的代码是否联系了始终在线并接受写入的节点?[​​=14=]

DSE Architecture guide, and especially Database Internals 部分很好地概述了 Cassandra 的工作原理。

让我们运行过一遍场景。

在写入 100K 行期间 (DC1) Node1 和 (DC2) Node3 进行了所有写入。当它正在发生时,Node1 也可能已经为 Node2 (DC1) 默认接受了 3 小时的提示,然后停止这样做。

一旦 Node2 重新联机,除非进行了修复 运行 - 需要一些时间才能通过重放提示来跟上进度。如果节点停机时间超过 3 小时,则必须进行修复。

在读取期间,技术上它可以根据驱动程序使用的负载均衡策略到达集群中的任何节点。除非指定执行 "DCAwareRoundRobinPolicy",否则读取请求甚至可能到达任何 DC(在本例中为 DC1 或 DC2)。由于请求的一致性是 "ONE",实际上任何 ALIVE 节点都可以响应 - 在这种情况下为 NODE1 和 NODE2 (DC1)。所以 NODE2 甚至可能没有所有数据,它仍然可以用 NULL 值响应,这就是为什么你有时会收到空数据而其他时候会更正数据的原因。

一致性 "ONE" 读取修复甚至不会发生,因为没有其他节点可以与之比较。这是上面的documentation。即使在一致性 "local_quorum" 或 "quorum" 的情况下,也会在 table 级别设置 read_repair_chance,默认为 0.1。这意味着只有 10% 的读取会触发 read_repair。这是为了通过不每次都触发来节省性能。想一想,如果读修复能够使table跨节点完全一致,那为什么"nodetool repair"还存在呢?

为避免这种情况,每当节点重新联机时,最佳做法是执行 "nodetool repair" 或 运行 具有一致性的查询 "local_quorum" 以获取一致的数据。

还要记住,一致性 "ONE" 与 RDBMS (WITH UR) 世界中的未提交读(脏读)相当。所以预计会看到意想不到的数据。