springboot2 mongodb 高效批量入库--环境搭建

当今使用微服务越来越多,每个服务都需要记录日志,那么记录到mysql中已完全不合适了。那么就记录到mongo中吧。

想要速度快,那么一定要使用批量保存,做过尝试入库10万数据,逐条插入的时间与批量入库的时间差别非常大。

做个测试。

1、本地搭建好一个mongodb数据库。怎么搭建,看前面的博文

2、springboot2集成springcloud搭建,怎么搭建,看前面的博文。

要点,主要在bootstrap.yml 配置文件中,增加mongodb配置引入即可。

spring:
  application:
    name: cwx-bus-message
  main:
    #当遇到同样名字的时候,是否允许覆盖注册不配置会报错 
    allow-bean-definition-overriding: true
  jackson:
    #过滤为null的值 需要返回值不为String
    default-property-inclusion: non_null
  cloud:
    config:
      name: mongodb,mysql-com,redis,oss,email,

 

 

 

 

 

 

 

3、mongodb配置。

配置中心中,增加一个mongodb-conf.yml

spring: 
  data: 
    mongodb: 
      uri: "mongodb://root:123456@192.168.1.252:27017/cwxdb?authSource=admin&authMechanism=SCRAM-SHA-1"

 

4、java接入mongodb。

接入mongodb的方法服务,主要是指定要接入的的集合,这里采用集合名称+月份

import java.util.Date;

import org.springframework.stereotype.Component;

import com.cwx.commons.utils.MyDateUtil;

/**
 * @Desc : 统一通用的接入mongodb入口
 * @author : 陈惟鲜 Chenweixian
 * @Date : 2022年12月6日 下午2:07:24
 */
@Component
public class CommonMgDao extends BaseMgDao {

    /**集合名称*/
    private String colName;
    
    public void setColName(String colName) {
        this.colName = colName;
    }

    @Override
    protected String getColName() {
        return colName + "_"+MyDateUtil.formatDate("yyyyMM", new Date());
    }
}

 

5、测试

5.0、测试基类

BastTest.java

在这里指定依赖信息,以及打印出方法执行的时长等

package com.test;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.jupiter.api.Test;
import org.junit.rules.TestName;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import com.cwx.BusMessageApp;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest(classes = BusMessageApp.class)
public class BaseTest {

    
    private Long starttime;
    @Rule
    public TestName junitClass= new TestName();
    @Before
    public void before() {
        starttime = System.currentTimeMillis();
        System.out.println(junitClass.getMethodName() + "....................start....................");
    }
    @After
    public void after() {
        double usedtime = (System.currentTimeMillis() - starttime) / 1000.0;
        System.out.println("耗时  " + usedtime + " ms");
        System.out.println(junitClass.getMethodName() + "....................end....................");
    }
    @Test
    public void hello() {
        System.out.println("hello world");
    }
}

 

 

package com.test;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

import com.alibaba.fastjson.JSON;
import com.cwx.api.bus.message.entity.LogMqVo;
import com.cwx.api.bus.message.entity.MgBaseVo;
import com.cwx.bus.message.dao.CommonMgDao;
import com.cwx.commons.utils.MyDateUtil;
/**
 * @Desc :测试mongodb 
 * @author : 陈惟鲜 Chenweixian
 * @Date : 2022年12月6日 下午2:10:21
 */
public class MongodbTest extends BaseTest {

    @Autowired
    CommonMgDao commonMgDao;
    /**设置数据*/
    private List<LogMqVo> initList(int count){
        List<LogMqVo> logs = new ArrayList<LogMqVo>();
        for (int i=0;i<count;i++) {
            LogMqVo log = this.genOne(i+"");
            logs.add(log);
        }
        return logs;
    }
    
    private LogMqVo genOne(String i) {
        LogMqVo log = new LogMqVo();
        log.setId(i+"");
//        @ApiModelProperty(value="创建人", dataType="String")
        log.setCreateName("chenweixian");
//        @ApiModelProperty(value="创建时间", dataType="Date")
        log.setCreateTime(new Date());
//        @ApiModelProperty(value="结束时间", dataType="Date")
        log.setUpdateTime(MyDateUtil.addHour(log.getCreateTime(), 1));
//        @ApiModelProperty(value="业务类型", dataType="String")
        log.setBizType("110");
//        @ApiModelProperty(value="业务类型", dataType="String")
        log.setBizTypeName("110系统");
//        @ApiModelProperty(value="请求报文", dataType="String")
        log.setReqContent("mq结果");
//        @ApiModelProperty(value="失败描述", dataType="String")
        log.setFailReason("失败原因");
//        @ApiModelProperty(value="from system, ServiceNameConstants", dataType="String")
        log.setSystemId("test");
        return log;
    }   
}

 

5.1、单条插入。

在以上MongodbTest测试类中,增加testSaveOneMqe
/**
     * 测试逐条插入
     * @author : 陈惟鲜 Chenweixian
     * @Date : 2022年12月6日 下午1:55:40
     */
    @Test
    public void testSaveOneMqe() {
        String colName = "test_one";
        List<LogMqVo> logs = initList(100000);
        for (LogMqVo log :logs) {
            commonMgDao.setColName(colName);
            commonMgDao.save(log);
        }
        System.out.println("finish test");
    }

测试结果

 

通过mongodb命令统计

db.test_one_202212.count()

 等待超过10分钟还是没插完。

 

5.2、测试批量插入。


在以上MongodbTest测试类中,增加testSaveAllMq
/**
     * 测试批量插入
     * @author : 陈惟鲜 Chenweixian
     * @Date : 2022年12月6日 下午1:55:51
     */
    @Test
    public void testSaveAllMq() {
        String colName = "test_batch";
        List<LogMqVo> logs = initList(100000);
        commonMgDao.setColName(colName);
        commonMgDao.saveAll(logs);
        System.out.println("finish test");
    }

测试结果,用了17s不到

 

 

 

testSaveAllMq....................start....................
2022-12-06 14:25:27.196  INFO 20728 --- [           main] org.mongodb.driver.connection            : Opened connection [connectionId{localValue:2, serverValue:93}] to 192.168.3.252:27017
2022-12-06 14:25:27.730  INFO 20728 --- [erListUpdater-0] c.netflix.config.ChainedDynamicProperty  : Flipping property: cwx-bus-share.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
finish test
耗时  16.144 ms
testSaveAllMq....................end....................

 

7、结论。

 

 

批量插入的速度是单条插入速度的N倍

 

posted on 2022-12-06 14:23  陈惟鲜的博客  阅读(676)  评论(0编辑  收藏  举报

导航