`

MongoDB 运维优化系列(二)

 
阅读更多

一个MQ,开5个线程,平均一天消费数据如下:

总表:249733  (upsert + $inc)

子表:1732389 (insert)

在数据量插入到这个级别的时候,数据库插入就有延迟了,延迟时间在5分钟以上,逐渐增大...

jstack <pid>走一发,看MQ消息线程状况,5个线程都是如下状况:

"main" prio=10 tid=0x00007f38ac009000 nid=0x1359 runnable [0x00007f38b3723000]
   java.lang.Thread.State: RUNNABLE
	at java.net.PlainSocketImpl.socketAccept(Native Method)
	at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:398)
	at java.net.ServerSocket.implAccept(ServerSocket.java:530)
	at java.net.ServerSocket.accept(ServerSocket.java:498)
	at org.apache.catalina.core.StandardServer.await(StandardServer.java:470)
	at org.apache.catalina.startup.Catalina.await(Catalina.java:781)
	at org.apache.catalina.startup.Catalina.start(Catalina.java:727)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:294)
	at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:428)

 注意其中一句话:java.lang.Thread.State: RUNNABLE

这表示线程正在运行,如果5个都这样,直白点就是线程繁忙。

 

此时,还不能确定问题所在,但要解决这个问题可以有三个方案,也可并行这三个方案:

1、增加MongoDB索引

2、增加消费线程数。(5->15)

3、将消息处理OnMessage内处理程序改为异步(即走线程池模式)

 

这三个方案,最快实施的则是方案1,于是方案1走一波,为了验证是否因索引导致,我们开启MongoDB慢日志,命令如下:

db.setProfilingLevel(1 ,50); 

 其中第一个参数:

0 –  不开启 

1 –  记录慢命令 (默认为>100ms)  

2 –  记录所有命令  

第二个参数:

n,慢操作执行时间,单位ms

执行成功后,系统会在DB下生成一个系统表

system.profile

这个表的结构如下:

{
    "op" : "update",
    "ns" : "chae_prod.oma_osoa_link_total",
    "query" : {
        "$and" : [ 
            {
                "nsCode" : {
                    "$eq" : "lyf"
                }
            }, 
            {
                "envCode" : {
                    "$eq" : "prod"
                }
            }, 
            {
                "minuteTime" : {
                    "$eq" : "2017-06-29 10:09"
                }
            }, 
            {
                "clientServiceName" : {
                    "$eq" : "back-order-web"
                }
            }, 
            {
                "serviceName" : {
                    "$eq" : "basics-stock-service"
                }
            }
        ]
    },
    "updateobj" : {
        "$set" : {
            "clientServiceName" : "back-order-web",
            "nsCode" : "lyf",
            "envCode" : "prod",
            "minuteTime" : "2017-06-29 10:09",
            "belongDate" : "2017-06-29",
            "serviceName" : "basics-stock-service"
        },
        "$inc" : {
            "successTotalNumber" : 1,
            "totalNumber" : 1,
            "failedTotalNumber" : 0
        }
    },
    "keysExamined" : 0,
    "docsExamined" : 213026,
    "nMatched" : 1,
    "nModified" : 1,
    "keyUpdates" : 0,
    "writeConflicts" : 0,
    "numYield" : 1669,
    "locks" : {
        "Global" : {
            "acquireCount" : {
                "r" : NumberLong(1670),
                "w" : NumberLong(1670)
            }
        },
        "Database" : {
            "acquireCount" : {
                "w" : NumberLong(1670)
            }
        },
        "Collection" : {
            "acquireCount" : {
                "w" : NumberLong(1670)
            }
        }
    },
    "millis" : 631,
    "execStats" : {},
    "ts" : ISODate("2017-06-29T10:19:58.387+08:00"),
    "client" : "10.10.254.15",
    "allUsers" : [],
    "user" : ""
}

 

 

 

其中millis字段表示执行时长,我们看到631MS,好高啊。

 

 

OK,我们迅速实施增加索引动作

我们在主表上增加upsert的query索引(也是前台查询索引):

 

{
    "nsCode" : -1,
    "envCode" : -1,
    "minuteTime" : -1,
    "clientServiceName" : -1,
    "serviceName" : -1
}

 

 

在子表上增加前台查询索引:

 

{
    "nsCode" : -1,
    "envCode" : -1,
    "endTime" : -1,
    "clientServiceName" : -1,
    "serviceName" : -1
}

 

 

增加完后,我们再查询数据,发现order最新时间的数据,OK出来了,和现在时间对的上了。

 再来看一下内存stack:

"pool-2-thread-1" daemon prio=10 tid=0x00007f385ce3c800 nid=0x1370 waiting on condition [0x00007f38a14f7000]
   java.lang.Thread.State: TIMED_WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000c6bd5740> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:226)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2082)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1090)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:807)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	at java.lang.Thread.run(Thread.java:745)

 “TIMED_WAITING (parking)”中的 timed_waiting 指等待状态,但这里指定了时间,到达指定的时间后自动退出等待状态;parking指线程处于挂起中。

这就表示我们的线程消费已经处于挂起状态了,比较清闲,等着自动回收了。

观察一段时间后,发现没有什么大的问题。

于是我们便不再执行2,3方案。

为了保险期间我增加了方案4:

方案4:删除历史数据

有两种方法实现方案4,一个是用 MongoDB自带的TTL,具体语法列一下,剩下的请度娘:

db.log_events.createIndex({"createdAt": 1},{expireAfterSeconds: 180}) #5分钟后过期

后面的参数单位是秒,180秒。

由于我们默认给MongoDB分配的是1G内存,我们还对 MongoDB内存进行了加大,增加到2G。

另一种就是你自己写JOB定时删了。好了方案优化到此结束。

期待与大家分享更多的MongoDB运维优化方案

 

分享到:
评论

相关推荐

    mongodb权威指南(第二版)

    本书的标题提到了“权威指南”,这意味着内容会非常全面和深入,涵盖了MongoDB的基础知识、安装配置、核心操作、高级特性、性能优化、安全机制、运维监控等各个方面。书中的内容应该包括但不限于以下方面: 1. 数据...

    MongoDB Performance Best Practices

    这些最佳实践关注于MongoDB Atlas作为数据库即服务(DBaaS)的部署和操作,包括如何在MongoDB Atlas上实现高性能和最佳的运维实践。 MongoDB Stitch: 后端即服务 MongoDB Stitch作为后端即服务(BaaS)提供者,为...

    mongoDB说明文档

    数据库管理是MongoDB运维的核心工作,这部分内容介绍了如何进行用户权限管理、备份恢复、性能监控等。 ### **34. MongoDB概念和术语(Mongo Concepts and Terminology)** 这部分内容定义了MongoDB中常用的概念和...

    nosqlbooster4mongo-7.0.8,MongoDB连接工具

    版本7.0.8是该工具的一个更新版本,提供了一系列增强的功能和优化,旨在提高开发人员和数据库管理员的工作效率。 NosqlBooster 4 MongoDB的主要特点包括: 1. **图形化用户界面**:它提供了一个直观的GUI(图形...

    MongoDB 4.0.4

    首先,MongoDB 4.0系列引入了混合交易(Hybrid Transactions),这是一项基于ACID(原子性、一致性、隔离性和持久性)原则的重要更新。这种新的事务处理能力使得MongoDB能够处理复杂的业务逻辑,提供跨文档的一致性...

    mongodb 4.0.22版本

    在 MongoDB 4.0 系列中,最重要的特性之一是引入了交易(Transactions),支持多文档ACID事务,这使得 MongoDB 更适合处理复杂的业务逻辑,尤其是在金融、电子商务等领域。在 4.0.22 版本中,可能已经对事务处理的...

    mongodb-linux-x86_64-rhel62-4.2.5.tgz

    在这个版本中,MongoDB引入了一系列的功能更新、性能优化和安全改进。 首先,让我们关注MongoDB的分片特性。在4.2.5版本中,MongoDB支持水平扩展,允许数据分布到多个分片上,以处理大量数据并提供高可用性。这使得...

    mongodb-4.2.2 压缩包

    这里我们关注的是 MongoDB 的 4.2.2 版本,它包含了一系列改进和新特性,旨在提供更好的性能和功能。 首先,让我们了解一下 MongoDB 的核心概念。MongoDB 使用 JSON 格式的文档(BSON)来存储数据,这种格式允许...

    mongodb3.2.4说明文档

    #### 二、MongoDB 安装指南 **2.1 支持的平台** MongoDB 支持多种操作系统,包括但不限于: - Windows(Server 2008 R2 及以上版本) - Linux(Ubuntu、CentOS、RHEL 等) - macOS(OS X 10.7 及以上版本) **...

    mongodb-linux-x86_64-3.4.6

    这个版本的MongoDB在2017年发布,提供了一系列增强的功能和性能优化。 MongoDB的主要特性包括: 1. 文档型数据模型:MongoDB以JSON格式的文档作为存储单元,这使得数据结构灵活,易于理解和操作。 2. 分片集群:...

    mongodb官方安装包

    8. **性能优化**:MongoDB提供了多种方式来优化性能,包括调整硬件资源分配、索引设计、查询优化等。 9. **监控与日志**:MongoDB的日志文件可以提供运行时的信息,帮助诊断问题。同时,通过监控工具,如MongoDB的...

    数据库运维2022版形考任务

    数据库运维是IT领域中的一个重要组成部分,它涉及到对数据库系统的安装、配置、监控、优化、备份、恢复以及安全性管理等一系列工作。在"数据库运维2022版形考任务"中,我们可以推测这是一份针对国开教育计算机网络...

    linux中MongoDB的安装包

    此外,定期检查MongoDB的日志文件以及进行性能优化和数据备份也是维护的重要部分。 以上就是在Linux环境下安装MongoDB 4.0.0的基本步骤。理解并熟练掌握这些步骤对于管理和运维MongoDB数据库至关重要。

    mongodb-linux-x86_64-3.0.2.tgz

    MongoDB在3.0.2版本中提供了一系列的重要特性和改进,使其在大数据管理和分布式系统中表现出色。 首先,MongoDB 3.0.2在性能方面进行了优化。它引入了新的存储引擎——WiredTiger,相比于之前版本的MMapV1,...

    MongoDB Architecture Guide

    Eliot Horowitz,MongoDB的联合创始人和CTO,在引言部分阐述了MongoDB的设计理念,即从现实世界的需求出发,解决传统关系型数据库存在的问题,并利用文档型数据库的数据模型提供一系列新的功能。 首先,MongoDB的...

    MongoDB权威指南.pdf 中文版

    索引是数据库性能优化的关键技术之一,本书中对MongoDB的索引创建和管理做了详细说明,包括如何建立单个字段索引、复合索引、地理位置索引等,以及如何通过索引优化查询速度。 聚合工具是MongoDB处理大量数据时的...

    Python-mtools一组脚本用于设置MongoDB测试环境并分析和可视化MongoDB日志文件

    `mtools` 提供了一系列脚本,帮助用户便捷地创建和配置MongoDB实例,包括启动、停止、复制集配置、数据导入导出等操作。这些脚本简化了繁琐的手动配置,使得开发者可以更专注于应用的开发和测试,而不是数据库的运维...

    MongoDB实战:MongoDB in Action

    2. **集合与文档**:在MongoDB中,数据库由一系列集合构成,集合又包含多个文档。这种结构类似于关系数据库中的表和行,但不需预定义模式,便于快速开发和迭代。 3. **查询语言**:MongoDB使用一种名为MQL(MongoDB...

    NoSQL Manager for MongoDB 3.8.2.4 管理工具

    总的来说,NoSQL Manager for MongoDB 3.8.2.4是一个强大而全面的MongoDB管理工具,它简化了数据库的日常管理任务,提升了开发和运维效率。无论是初学者还是经验丰富的数据库管理员,都能从中受益。

    MongoDB服务及行业应用方案概述.pdf

    - 通过实施这一系列措施,有效地降低了使用MongoDB的风险,同时规范了使用方式,扩大了使用范围,并提高了使用水平。 - 架构规划方面,我们协助制定了明确的标准和规范,确保了MongoDB在项目中的合理应用。 - 开发...

Global site tag (gtag.js) - Google Analytics