【发布时间】:2016-11-11 12:46:17
【问题描述】:
我在 Cassandra 中有一个存储 csv 文件版本的表。它使用具有唯一 id 的版本(分区键)和行号(集群键)的主键。当我插入新版本时,我首先对要插入的分区键执行删除语句,以清理任何不完整的数据。然后插入数据。
现在问题来了。即使删除和后续插入在应用程序中一个接一个地同步执行,Cassandra 中似乎仍然存在某种程度的并发性,因为当我事后阅读时,我插入的行偶尔会丢失 - 大约 3 次中有 1 行。以下是一些事实:
- 卡桑德拉 3.0
- 一致性 ALL (R+W)
- 使用 Java 驱动程序删除
- 使用 Spark-Cassandra 连接器插入
- 节点数:2
- 复制因子:2
我执行的删除语句是这样的:
“从 myTable 中删除版本 = 'id'”
如果我省略它,问题就会消失。如果我在删除和插入之间插入延迟,则问题会减少(丢失的行更少)。最初我使用限制较少的一致性级别,我确信这是问题所在,但它并没有影响问题。我的假设是,出于某种原因,尽管 ALL 的一致性级别,删除语句仍被异步发送到副本,但我不明白为什么会出现这种情况或如何避免这种情况。
【问题讨论】:
-
一般来说,C* 是一个最终一致的数据库。这意味着很多不同的东西,但你不能依赖操作顺序。永远不要尝试连续做一些相关的操作。最好重新设计您的架构并改变您的方法。如果您发布您的数据模型并解释您希望实现的目标,我们可能会为您提供帮助。据我所知,在您的情况下,最好在客户端进行数据检索后过滤旧版本。
-
我的期望是最终的一致性程度会受到我选择的一致性级别的限制。现在,为了简单起见,我们在原型中使用 ALL,因为它不是瓶颈。如果我不能依赖以最保守的一致性级别按顺序完成的操作序列,那么我可以将一致性级别用于什么?
-
ALL 保证所有节点都对查询达成共识(因此在单个查询之后,所有节点都将具有相同版本的受影响行),但不保证任何关于查询顺序的内容。我强烈建议您重新设计您的方法并停止将 C* 视为关系数据库。那是行不通的。
-
根据文档 ALL 将保证它被写入所有节点上的提交日志,这将保证给定相关时间戳的顺序(尽管罗素在下面对这些时间戳的分配有一个很好的观点,但这可以在查询中解决)。
-
是的,但你不能保证处理顺序......无论如何,除非你有非常少量的写入,否则以所有一致性执行所有写入是一个坏主意。您可以通过重新设计方法来解决问题并提高效率。