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倍