意外的mongodb更新被阻止

时间:2017-06-06 20:04:39

标签: java mongodb morphia

我正在对一个分片的mongo集群(5个分片)执行查询和更新操作,并遇到了一个相当不寻常的问题(我甚至很难清楚地描述)。这是应用程序设置:

  • Mongo v3.0.12
  • Java 8(独立JVM)
  • Morphia v1.3.2

主要分片上的典型后台负载如下所示(使用mongostat):

insert query update delete getmore command % dirty % used flushes vsize   res qr|qw ar|aw netIn netOut conn set repl     time
     4  3120    785     *0     172   577|0     0.9   80.7       0 72.7G 40.9G   0|1   2|7    2m   163m 3420 rs0  PRI 15:46:29
     4  2324    475     *0     129   417|0     1.3   80.9       0 72.7G 40.9G   0|0   3|2    1m   124m 3420 rs0  PRI 15:46:30
     1  2503    425     *0     121   290|0     1.4   81.0       0 72.7G 40.9G   0|1   1|6    1m   114m 3420 rs0  PRI 15:46:31
     4  2322    469     *0     194   371|0     1.6   81.1       0 72.7G 40.9G   0|2   1|1    1m    86m 3420 rs0  PRI 15:46:32
     4  3349    435     *0     194   443|0     1.8   81.2       0 72.7G 40.9G   0|0   1|1    2m    83m 3420 rs0  PRI 15:46:33
     2  3071    474     *0     159   338|0     2.2   81.6       0 72.7G 40.9G   0|0   1|0    1m    87m 3420 rs0  PRI 15:46:34
     2  2661    394     *0     119   239|0     2.3   81.6       0 72.7G 40.9G   0|0   1|8  925k    81m 3420 rs0  PRI 15:46:35

与主分片的连接:

rs0:PRIMARY> db.serverStatus().connections
{
        "current" : 3388,
        "available" : 47812,
        "totalCreated" : NumberLong(338643)
}

RS0资源统计:

AWS System stats

希望能够确定场景。然后,我有两个应用程序服务器,它们与同一个DB但不同的集合进行交互:

  • 应用程序服务器A对集合1执行查询和更新
  • 应用程序服务器B对集合2执行查询和更新

我最近向应用服务器B添加了一个新的$ set更新操作,它似乎产生了令人遗憾的副作用,即显着降低了应用服务器A上的更新性能(这样以前运行时间<1秒的操作现在正在计时在~60秒)。

我相信是这种情况,因为应用服务器A的新的CPU分析在应用服务器B上运行set操作时产生以下结果:

Performance of update with SET operation

分析器中的相同节点没有在应用程序服务器B上运行的设置操作:

Performance of update without SET operation

我注意到,在新的SET操作期间(在应用程序服务器B上),mongo更新操作(在应用程序服务器A上)占用了总CPU时间的约25%。虽然SET操作没有运行,但等效操作仅消耗〜5%。

我最初的假设是我在mongo集群上遇到了某种性能瓶颈。我考虑了各种原因:

以下是来自RS0的mongostat输出,而SET操作正在应用服务器B上运行:

insert query update delete getmore command % dirty % used flushes vsize   res qr|qw ar|aw netIn netOut conn set repl     time
    *0  1405      1     *0      19   132|0     0.0   80.0       0 72.1G 40.9G   0|0   1|0  153k    11m 3419 rs0  PRI 15:46:08
    *0  1340     *0     *0      18   121|0     0.0   80.0       0 72.1G 40.9G   0|0   1|0  144k     7m 3419 rs0  PRI 15:46:09
    *0  1677     *0     *0      27   263|0     0.0   80.1       0 72.1G 40.9G   0|0   1|0  230k     9m 3419 rs0  PRI 15:46:10
    *0  1415      4     *0      35   198|0     0.0   80.0       0 72.1G 40.9G   0|0   1|0  183k     9m 3419 rs0  PRI 15:46:11
    *0  1350     *0     *0      17   123|0     0.0   80.0       0 72.1G 40.9G   0|0   1|0  143k    14m 3419 rs0  PRI 15:46:12
    *0  1036     *0     *0      21   141|0     0.0   80.0       0 72.1G 40.9G   0|0   1|0  130k     9m 3419 rs0  PRI 15:46:13
     1  1099     *0     *0      20   139|0     0.0   80.0       0 72.1G 40.9G   0|0   2|0  132k     8m 3419 rs0  PRI 15:46:14

我注意到负载显着下降。 AWS系统指标显示了类似的图片,CPU负载和CPU的下降。网络IN / OUT。

是SET操作期间进入节点的连接数:

rs0:PRIMARY> db.serverStatus().connections
{
        "current" : 3419,
        "available" : 47781,
        "totalCreated" : NumberLong(338788)
}

是的,连接数量有所增加,但没有达到我认为是问题的程度。

然后我考虑了SET操作可能很慢,所以我启用了dbMS profiling,其慢速阈值为2秒。在SET操作期间,慢查询日志只获得一个条目(这是由于应用程序服务器A上已知的慢速操作),因此也没有帮助。

然后我查看了日志卷的性能,它被配置为使用实例SSD存储,使用iostat:

iostat -x 5 -t

这同样显示了与mongostat类似的图片,即当我看到应用程序服务器A上的减速/阻塞更新时,负载似乎减少,而SET操作正在运行时正在应用程序服务器B上运行。

不幸的是,这是我用完想法和调试想法的地方。我非常感谢您在解决这个问题时提供进一步的帮助。

1 个答案:

答案 0 :(得分:0)

看来这个问题的原因是:

  • 如果副本开始滞后,使用多数写入关注会阻止任何其他数据库操作进入同一个mongo集群。
  • 延迟的原因是我们使用$ push,这会在oplog中为特定分片创建热点,请参阅https://jira.mongodb.org/browse/SERVER-9784以获取更多信息。