如果任一集群永远未修复,Cassandra 或 ScyllaDB 能否在使用 PySpark 读取时提供不完整的数据?

Can Cassandra or ScyllaDB give incomplete data while reading with PySpark if either clusters are left un-repaired forever?

我同时使用 Cassandra 和 ScyllaDB 三节点集群,并使用 PySpark 读取数据。我想知道它们中的任何一个是否不会永远修复,如果节点中存在不一致,从其中任何一个读取数据时是否存在任何挑战。是否会读取到正确的数据,如果是,那我们为什么要修复它们?

是的,如果未完成 reapir,您可能会得到不正确的数据。它还取决于您阅读或写作的一致性。通常在生产系统中,写入是用 (Local_one/Local_quorum) 完成的,读取是用 Local_quorum.

如果您以弱一致性级别编写,那么修复就变得很重要,因为某些节点可能没有发生突变,并且在读取这些节点时可能会被选中。

例如,如果您在 table TABLE1 上以一致性级别 ONE 写入,复制为 3。现在您的写入可能会写入 NodeA只有 NodeBNodeC 可能错过了突变。现在,如果您使用一致性级别 LOCAL_QUORUM 阅读,可能会选择 NodeB 和 'NodeC' 而它们不会 return 写入数据。

修复是 Cassandra 的一项重要维护任务,应定期和持续进行,以保持数据处于健康状态。

除了 Manish 的出色回答外,我还要补充一点,读取操作 运行 一致性级别 *_ONE 更高 具有(小.. .10% 默认)调用 read repair 的机会。我已经看到应用程序 运行 在更高的读取一致性级别上,不一致副本的问题会更少。

尽管如此,写在 *_QUORUM 应该确保大多数(仲裁)副本确实是一致的。写入成功后,数据不应随时间“变坏”。

综上所述,运行宁定期(每周)维修是个好主意。我强烈建议使用 Cassandra Reaper 来管理维修,尤其是当您有多个集群时。

正如其他人在其他答案中指出的那样,由于不同的原因,不同的一致性级别使修复或多或少变得重要。因此,我将重点关注您在使用的评论中所说的一致性级别:LOCAL_ONE 用于阅读,LOCAL_QUORUM 用于写作:

用LOCAL_QUORUM写入成功只能保证写入了两个副本。如果第三个副本暂时关闭,稍后会出现 - 此时三分之一的数据读取请求,仅从一个节点完成的读取(这就是 LOCAL_ONE 的意思)将错过新数据!此外,甚至无法保证所谓的 单调一致性 - 您可以在一次读取中获取新数据(从一个节点),并在以后的读取中获取旧数据(从另一个节点)。

但是,只有维修才能解决此问题的说法并不完全准确。另一个功能——在 Cassandra 和 Scylla 上默认启用——称为 Hinted Handoff——当一个节点停机时间相对较短时(最多三个小时,但也取决于该时期的流量),其他尝试向其发送更新的节点会记住这些更新 - 并在死节点恢复时重试发送。如果您只面临如此短的停机时间,则无需维修,实际上 Hinted Handoff 就足够了。

也就是说,Hinted Handoff 不能保证完美,可能会遗漏一些不一致的地方。例如,希望保存提示的节点可能会在它设法保存提示之前自行重启,或者在保存提示后被替换。所以这个机制并不是万无一失的。

顺便说一句,还有一件事您需要注意:如果您曾经打算进行修复(例如,可能在某个节点停机时间过长提示 Handoff 已经工作,或者可能是因为 QUORUM 读取导致 读取修复 ),您必须至少每 gc_grace_seconds 执行一次(默认为 10 天)。 此声明的原因是 数据复活 的风险太少了。问题是,在 gc_grace_seconds 之后,标记已删除项目的 tombstones 将被永久删除(“垃圾收集”)。那时,如果您进行修复并且其中一个节点恰好具有此数据的旧版本(在删除之前),则旧数据将“复活” - 复制到所有副本。