到目前为止,我一直认为您无法真正删除基于复制的分布式数据库中的行。这一切都适用于基于副本的副本。但是在 Replication 中,您将它们标记为“考虑此删除”,并在每个最后的查询中将它们过滤掉。但是您实际上并没有从数据库中删除某些内容。我认为是时候验证该假设是否正确了。
我的理解是,如果发生键冲突,您将遇到复制的竞争条件。它是这样的:
数据库A: 在键 11 (11A) 下添加条目
数据库 B: 在键 11 (11B) 下添加条目
数据库A: 删除键 11 下的条目
现在这取决于这 3 个操作在野外“相遇”的顺序: 预期顺序为:
- 11A 创建
- 11 删除(即 11A)
- 11B 创建
但如果发生这种情况怎么办?
- 11A 创建
- 11B 创建(失败,已经是 key 11)
- 11 删除
或者更糟的是,这个?
- 11B 创建
- 11A 创建(失败,已经是key 11)
- 11 删除(将命中 11B)
最佳答案
我假设我们正在谈论一个无领导者的分布式数据库,即所有节点都扮演相同角色(没有主节点)的数据库,因此所有节点都可以为读取和写入提供服务。否则,如果只有一个主控,它可以对所有写入/删除施加特定的顺序,从而解决您描述的并发问题。
But in Replication you mark them as "consider this delete" and filter them out in every last query.
没错,这样做主要有两个原因:
- 正确性:如果项目被删除而不是逻辑删除,则可能存在不明确的实例,其中查询 2 个节点,其中节点 A 有项目但节点 B 没有。并且整个系统无法区分该项目是否被删除(但在 A 中删除失败)或该项目是否是最近创建的(但在 B 中创建失败)。使用墓碑,可以清楚地说明这种区别。
- 性能:这些系统中的大多数不执行就地更新(如 RDBMS 数据库通常执行的那样),而是执行仅追加操作。这样做是为了提高性能,因为磁盘中的随机访问操作比顺序操作慢得多。因此,通过墓碑执行删除与此方法非常吻合。
But you do not ever actually delete something from the DB.
这不一定是真的。通常,逻辑删除最终会从数据库中删除(以垃圾收集方式)。最终这里意味着当系统可以确定上述示例不会再发生这些项目时,它们将被删除(因为删除已传播到所有节点)。
My understanding is that you would run into a Race Condition with the Replication if there was ever a key collision
这适用于大多数此类分布式系统。结果将取决于操作到达数据库的顺序。但是,其中一些数据库提供了替代机制,例如条件写入/删除。通过这种方式,您只能删除项目的特定版本或仅当其版本为特定版本时才更新项目(因此如果其他人同时更新它则中止更新)。来自 Cassandra 的此类操作的一个示例是 conditional deletes和所谓的lightweight transactions
下面是一些描述 Riak 和 Cassandra 如何执行删除的引用资料,其中还包含大量有关墓碑的信息:
关于database - 你能在基于复制的分布式数据库中删除吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49899012/