【问题标题】:MongoDB Write and lock processesMongoDB 写入和锁定进程
【发布时间】:2014-11-10 13:11:32
【问题描述】:

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

这就是我目前对这个过程的理解,请纠正我的错误

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

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

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

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

西蒙

【问题讨论】:

    标签: mongodb replication locks journaling


    【解决方案1】:

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

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

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

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

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

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

    希望这会有所帮助。

    【讨论】:

    • 感谢您提供信息丰富的回复,我一直忙于回复。很高兴知道我不是唯一一个不完全理解这个过程的人。我想我理解你,但要确认一下,你是说所有数据最初都写入内存,然后每 100 毫秒(或任何配置),日志被写入磁盘。然后每隔 SyncDelay 秒将 oplog 和数据库数据写入磁盘。
    • 这确实有道理,但是我对此的一个担忧是,如果数据在同步到磁盘之前从内存中删除。这是否意味着更改不会同步?该日志仍将在磁盘上(每 100 毫秒同步一次),因此如果从内存中丢失,可能会重播。尽管如此,如果内存被丢弃,数据仍然可能丢失,直到在 syncDelay 秒重播日志之前。你知道Mongo是否有办法解决这个问题吗?也感谢关于锁的提示,这肯定已经解决了问题。
    • 没有 100% 的安全性。如果数据只在内存中,而服务器出现故障,则数据丢失。如果您希望降低发生这种情况的可能性,则必须将写入关注点设置为 w>1 或多数,并具有地理分布的副本集成员
    • MongoDB blog 上有一组很棒的插图,解释了日志过程是如何工作的。
    • 我并没有真正提到数据持久性,即在内存中丢失数据的意义上。我的思路更倾向于将数据从内存中删除并放置在磁盘日志中,这意味着数据在磁盘日志被刷新之前不会出现在读取中。感谢您的链接,我在发布此内容的那天在 Kristina Chodorow 的博客上阅读了它:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多