非 ACID RethinkDB 或 MongoDB 如何维护非相等查询的二级索引

Posted

技术标签:

【中文标题】非 ACID RethinkDB 或 MongoDB 如何维护非相等查询的二级索引【英文标题】:how do non-ACID RethinkDB or MongoDB maintain secondary indexes for non-equal queries 【发布时间】:2013-08-12 08:51:48 【问题描述】:

这更像是“内部运作”不解的问题:

不支持*A*CID(意味着它们不能在单个事务中更新/插入然后回滚多个对象的数据)的noSQL数据库如何更新二级索引?

我的理解是——为了保持二级索引同步(否则它会变得陈旧读取)——这必须发生在同一个事务中。

此外,如果索引可以驻留在与数据不同的主机上,则需要存在分布式锁和/或两阶段提交才能使此类更新以原子方式工作。

但是如果这些数据库不支持多对象事务(这意味着它们不会跨多个主机对数据进行两阶段提交),它们使用什么方法来保证驻留在 B 树结构中的二级索引分开的数据不会陈旧吗?

【问题讨论】:

【参考方案1】:

这是一个很好的问题。

RethinkDB 始终将二级索引与表的主索引/数据存储在同一主机上。即使在连接的情况下,RethinkDB 也会对数据进行查询,因此二级索引、主索引和数据始终位于同一节点上。因此,不需要像两阶段提交这样的分布式锁定协议。

RethinkDB 确实支持一组有限的事务功能——单文档事务。对单个文档的更改以原子方式记录。相关的二级索引更改也被记录为该事务的一部分,因此要么记录整个更改,要么根本不记录任何内容。

扩展有限的事务功能以支持单个分片中的多个文档很容易,但跨分片很难做到(出于您提到的分布式锁定原因),因此我们决定不实现事务对于多个文档。

希望这会有所帮助。

【讨论】:

澄清一点。表的每个分片都包含该分片的所有索引数据。这意味着每个索引的副本与副本的数量一样多。说“记录整个更改,或者什么都不记录”是不正确的。每个副本将记录或不记录更改(以及由此产生的索引更改)。副本,因此其索引可能已过期(并且可以通过传递use_outdated = True 标志访问过时的数据。此数据永远不会被在没有设置该标志的情况下使用,最终将被更新。【参考方案2】:

这是一个 MongoDB 答案。

我不太确定你的逻辑是什么。更新二级索引与能否回滚多语句事务(例如多次更新)无关。

MongoDB 每个文档都有事务,这对于更新索引很重要。如果需要,这些操作可以使用日志来反转。

这必须发生在同一笔交易中。

是的,就像 RDBMS 一样。你应用的索引越多,你的写入速度就越慢,在我看来你知道为什么。

当写入发生时,MongoDB 将使用适用于特定索引的字段更新适用于该集合的所有索引。

此外,如果索引可以驻留在与数据不同的主机上

我不确定 MongoDB 是否允许这样做,我相信它有一个 JIRA;但是,我目前找不到那个 JIRA。

然后需要存在分布式锁和/或两阶段提交,这样更新才能以原子方式工作。

很有可能。允许此功能将......好吧,我们只是说创建一个毛球。

即使在分片设置中,每个范围的索引也驻留在分片本身,而不是配置服务器上。

但是如果这些数据库不支持多对象事务(这意味着它们不会跨多个主机对数据进行两阶段提交)

这不是两阶段提交的意思。我相信您需要重新了解什么是两阶段提交:http://docs.mongodb.org/manual/tutorial/perform-two-phase-commits/

我想如果你说的交易覆盖多个分片,嗯,好吧。

他们使用什么方法来保证位于与数据分离的 B 树结构中的二级索引不会过时?

Agan 我不确定为什么多文档事务会影响索引是否过时,因为您没有跨文档分组。唯一的例外是唯一索引,但也适用于单个文档更新;请注意,它的唯一性在分片设置中有点毛茸茸,无法保证。

在您创建的索引中,通常每个文档前缀键都有一个条目,除非它是文档上的多键索引,那么您可以创建多个索引,但是,无论哪种方式索引更新都是针对单个对象完成的,而不是通过多文档交易,我不确定您在这里的逻辑是什么,因此这就是我给出的答案。

【讨论】:

两阶段提交是一种用于跨多个主机维护事务完整性的协议。所以是的,我说的是跨多个主机的“多个文档上的事务”。所以问题是:如果 Mongo 和 Rethink 今天不做两阶段提交事务,他们如何在不同于数据的分片上维护二级索引。我认为您的答案是——他们不会在与数据不同的分片上维护二级索引。因此他们不需要分阶段提交 @VP 好的,所以你的意思是在一个分片集中,然后:是的,他们不会在另一个分片上维护那个索引,而且两阶段提交不需要在两个主机之间,它是两个不同事务作为一个操作完全原子的情况 好的,Mongo 可以理解。希望得到一些关于 rethinkDB 的反馈。 Rethink 有连接,这意味着索引可能在与数据主机不同的主机的内存中。 2阶段提交也需要单独的主机:“分布式事务是一个操作包,其中涉及两个或多个网络主机”en.wikipedia.org/wiki/Two-phase_commit_protocol @VP 我在该页面上没有找到该文本 @Sammaya:上面的 2phase 提交链接有文本“它是一种分布式算法,用于协调参与分布式原子事务的所有进程”。然后通过此链接en.wikipedia.org/wiki/Distributed_transaction 给出分布式原子事务 的定义。这个链接有我在声明 2phase 提交必然涉及多个主机时提到的文本【参考方案3】:

RethinkDB 始终将二级索引数据与其索引数据存储在同一台机器上。这允许它在同一事务中更新。 Rethink 承诺对单个文档操作具有 ACIDy,并将文档的索引视为文档本身的一部分。

【讨论】:

以上是关于非 ACID RethinkDB 或 MongoDB 如何维护非相等查询的二级索引的主要内容,如果未能解决你的问题,请参考以下文章

不向 rethinkdb 插入数据

如何在 Ubuntu 上卸载 RethinkDB?

没有关系数据库的 ACID 属性如何帮助非关系数据库更好地执行?

Rethinkdb复制和数据一致性

RethinkDB:​​根据过滤字段过滤文档

socket.io vs RethinkDB changefeed