4

我最近读了很多关于 MongoDB 的文章,但是我找不到任何明确的材料,就是数据是如何写入日志和 oplog 的。

所以这就是我到目前为止对这个过程的理解,请纠正我哪里错了

  • 客户端连接到 mongod 并执行写入。写入存储在套接字缓冲区中
  • 当 Mongo 可用时(此时不确定可用是什么意思),将数据写入日志?
  • mongoDB 文档然后说每 60 秒写入一次从日志刷新到磁盘。通过这个,我只能假设这意味着写入主节点和 oplog。如果是这种情况,如何在 60 秒同步间隔之前出现写入?
  • 一段时间后,辅助节点从主节点或其同步源中吸取数据并更新其 oplog 和数据库。关于这种情况究竟何时发生以及是什么延迟了它似乎非常模糊。

我还想知道是否禁用了日志记录(我知道这是一个非常糟糕的主意),oplog 和数据库在什么时候更新?

最后,我有点难过在这个过程中的哪个点创建了写锁。这只是在更新数据库和 oplog 时还是在其他时候?

感谢任何可以对此有所了解或向我指出一些阅读材料的人。

西蒙

4

1 回答 1

4

据我了解,这就是发生的事情。我简化了一点,但它应该清楚它是如何工作的。

  1. 客户端连接到 mongo。到目前为止没有写入,也没有断开连接,因为它真的取决于现在发生的写入问题。让我们假设我们使用(在撰写本文时)默认的“已确认”。
  2. 客户端发送它的写操作。这是我真的不确定的地方。在此步骤或下一个步骤之后,确认将发送给驱动程序。
  3. 写操作通过查询优化器运行。在这里发送确认,因为在确认的写入问题中,您可能会收到重复键错误。这可能是在最后一步中检查的。如果我应该打赌,我会说是在这个之后。
  4. 查询优化器的输出然后应用到内存中的数据实际上是内存映射数据文件的数据,内存映射的 oplog 和日志的内存映射文件。从该内存映射部分回答查询,或者将相应的数据映射到内存以回答查询。如果存在,oplog 也会从内存中读取。
  5. 一般每 100 毫秒,日志就会同步到磁盘。精确值由许多因素决定,其中之一是journalCommitInterval 配置参数。如果您有日志的写入问题,现在将通知驱动程序。
  6. syncDelay秒,内存映射文件的当前状态都会同步到磁盘我认为日志被截断为尚未应用于数据的条目,但我不太确定,因为它基本上不应该发生日志中的数据尚未应用于当前数据。

如果您仔细阅读,您会注意到数据早在通过查询优化器运行并应用于映射到内存的文件时就已为 oplog 准备好。当 oplog 条目被其中一个辅助节点拉取时,它会立即应用于内存映射文件的数据,并以与主节点相同的方式同步到磁盘中。

一些需要注意的事项: 相对较小的数据一旦写入日志,是相当安全的。如果一个节点在两次同步到数据文件之间发生故障,则数据文件和 oplog 都可以从它们在数据文件和日志中的最后状态恢复。一般来说,您可以拥有的最大数据丢失是上次提交后记录到日志中的操作,中位数为 50 毫秒。

至于锁。如果您写得仔细,当数据同步到磁盘时,不会在数据库级别上施加锁定。可以创建写锁以确保在任何给定时间点只有一个线程修改给定文档。还有其他可能的写锁,但一般来说,它们应该很少见。

文件系统层上的写锁只创建一次,尽管只是隐式的,iirc。在应用程序启动期间,会在 dbpath 的根目录中创建一个锁定文件。当存在有效锁时,任何其他 mongod 实例都将拒绝对这些数据文件执行任何操作。你也不应该;)

希望这可以帮助。

于 2014-09-16T18:18:21.217 回答