如何避免在mongodb中锁定

如何避免在mongodb中锁定,mongodb,Mongodb,我有一个集合,它有并发读取,也有应用程序的某些部分更新同一个集合,但在加载过程中,每个读取和更新操作占用了大量的时间,并且随着时间的推移变得非常缓慢 下面是一些查询的日志 nscanned:4 nupdated:2 keyUpdates:3 numYields: 1 locks(micros) w:2475463 10247ms nscanned:4 nupdated:2 keyUpdates:2 numYields: 1 locks(micros) w:2077481 1054ms 集合只

我有一个集合,它有并发读取,也有应用程序的某些部分更新同一个集合,但在加载过程中,每个读取和更新操作占用了大量的时间,并且随着时间的推移变得非常缓慢


下面是一些查询的日志

nscanned:4 nupdated:2 keyUpdates:3 numYields: 1 locks(micros) w:2475463 10247ms
nscanned:4 nupdated:2 keyUpdates:2 numYields: 1 locks(micros) w:2077481 1054ms
集合只有70K条记录。 并发读写几乎是10

这是我已经做过的

  • 具有3个成员副本集的分片

  • 分片键是散列的,并且db和集合级分片都是可加密的

  • 每个副本盒都有足够的电源和ram

  • 查询以索引为界,
    db.collection.find().explain()
    具有此输出

    {
        "cursor" : "BtreeCursor fp.ulc_1_c_1_p_1",
        "isMultiKey" : true,
        "n" : 0,
        "nscannedObjects" : 2,
        "nscanned" : 2,
        "nscannedObjectsAllPlans" : 2,
        "nscannedAllPlans" : 2,
        "scanAndOrder" : false,
        "indexOnly" : false,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "millis" : 0,
        "indexBounds" : {
            "fp.ulc" : [
                [
                    "0ca01c47c984b5583d455e42aafded2c",
                    "0ca01c47c984b5583d455e42aafded2c"
                ]
            ],
            "c" : [
                [
                    false,
                    false
                ]
            ],
            "p" : [
                [
                    1372062247612,
                    1.7976931348623157e+308
                ]
            ]
        }
    }
    
  • 我也尝试过用secondary设置阅读首选项,但过了一段时间后,速度也变慢了 我还注意到mongostat中的锁是mongostat的输出

    insert  query update delete getmore command flushes mapped  vsize    res faults       locked db idx miss %     qr|qw   ar|aw  netIn netOut  conn  set repl       time
        *0     *0      6     *0       4     2|0       0  54.4g   109g  1.74g      0 collectDb:199.7%          0       6|0     0|1     3k   130k    21 set1  PRI   08:27:55
        *0     *0     15     *0      11     8|0       1  54.4g   109g  1.74g      0 collectDb:200.1%          0       6|0     0|1    11k   357k    21 set1  PRI   08:27:58
         7     *0     34     *0      18    26|0       0  54.4g   109g  1.75g      0 collectDb:202.9%          0       6|0     0|1    36k   362k    21 set1  PRI   08:28:00
         1     *0     13     *0       8     7|0       0  54.4g   109g  1.75g      0 collectDb:192.3%          0       6|0     0|1    12k   287k    21 set1  PRI   08:28:03
         1     *0      9     *0       7     8|0       0  54.4g   109g  1.75g      0 collectDb:196.1%          0       6|0     0|1     5k   258k    21 set1  PRI   08:28:04
         5     *0     20     *0      10    13|0       0  54.4g   109g  1.75g      0 collectDb:207.7%          0       6|0     0|1    23k   214k    21 set1  PRI   08:28:08
         8     *0     38     *0      21    29|0       0  54.4g   109g  1.74g      0 collectDb:215.9%          0       5|0     0|1    40k   548k    21 set1  PRI   08:28:12
         6     *0     44     *0      24    22|0       0  54.4g   109g  1.75g      0 collectDb:199.5%          0       3|0     0|1    45k   509k    21 set1  PRI   08:28:15
         2      4     27     *0      11    28|0       0  54.4g   109g  1.75g      0 collectDb:169.2%          0       6|0     0|1    21k   318k    21 set1  PRI   08:28:18
         2     *0     29     *0      18    20|0       0  54.4g   109g  1.74g      0 collectDb:255.5%          0       5|0     0|1    28k   588k    21 set1  PRI   08:28:24
    

    所以我终于想出了一些避免锁定mongodb的最佳方法

    我所做的

    • 将我的mongodb更新为最新的稳定生产版本2.4.8

    • 使用将我的ebs更新为优化的iops 2000

    • 从mongod.log文件监视我的慢速查询,并对每个驱动器执行iowait

    • 添加了一些多键索引和复合索引

    • 我还观察了每个ec2实例上的ram消耗情况,包括副本集的主成员和辅助成员

    • 通过千兆以太网接口和每台服务器上超过16 gb的ram优化Ebs类型,以便大部分时间ram可用于索引和当前数据集

    • 这是一个很好阅读的amazon实例及其最佳用例,这样您就可以更好地理解您的需求


    虽然锁定是MongoDB中的一个主要问题,但我认为他们正在研究集合级锁定,因此在即将发布的版本中,它将解决几乎所有与锁定导致的性能降低相关的问题。
    这是您可以检查状态的链接。

    正在进行哪些更新?他们是在添加新字段还是只是在替换现有字段?他们在现有文档中添加新关键字添加新关键字的确切含义是什么?请你详细说明一下好吗。感谢您使用这样的文档{a:1,b:[{c:1},{d:1}]},下次我将某个对象推到b中。原因可能是在MongoDB中,该文档在RAM中分配/填充了一定量的空间,因此无需从磁盘获取。但是,当您添加新字段(例如添加到b数组中的字段)时,文档的增长有时会超过分配的空间,因此它会将文档写入磁盘。这导致阻塞不一致。您可以尝试将要添加的所有值存储在数据结构中,然后编写脚本来更新MongoDB文档。这将被称为就地更新。这样做很有用。祝你一切顺利。