场景:前台传来大量数据,需要插入到redis和mysql中,同时进行速度缓慢,还容易丢失数据。下面进行模拟测试。
//写入mysql时间: 4ms
//写入redis时间: 78055ms
//直接批量写入mysql
//写入mysql时间: 4ms
//单条写入mysql
//写入mysql时间: 258971ms
@Test
public void CreateCollection() {
long startTime = System.currentTimeMillis();
ArrayList<Department> departmentList = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
Department department = new Department();
department.setId(i);
department.setName("研1发部" + i);
department.setDescr("开1发产品" + i);
//单条记录新增插入
//departmentMapper.insert(department);
//redis新增
//redisDao.set(department.getId().toString(), department.getName());
departmentList.add(department);
}
long endTime = System.currentTimeMillis();
TraverseCollection(departmentList);
System.out.println("集合生成加redis写入缓存时间: " + (endTime - startTime) + "ms");
}
public void TraverseCollection(ArrayList<Department> departmentList) {
long startTime = System.currentTimeMillis();
//创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
cachedThreadPool.execute(new Runnable() {
@Override
public void run(){
//批量新增mysql
departmentMapper.insertDepartmentList(departmentList);
}
});
long endTime = System.currentTimeMillis();
System.out.println("集合解析加写入mysql时间: " + (endTime - startTime) + "ms");
}
数据脚本
<insert id="insert" parameterType="com.cxy.template.entity.Department">
insert into department(id,name,descr) values(#{id},#{name},#{descr})
</insert>
<insert id="insertDepartmentList" parameterType="java.util.List">
insert into department(id,name,descr) values
<foreach collection="departmentList" item="dml" separator=",">
(#{dml.id},#{dml.name},#{dml.descr})
</foreach>
</insert>
连接池配置
#表明使用Druid连接池
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
#初始化时建立物理连接的个数。
spring.datasource.druid.initial-size=5
#最大连接池数量
spring.datasource.druid.max-active=20
#最小连接池数量
spring.datasource.druid.min-idle=5
#获取连接时最大等待时间,单位毫秒
spring.datasource.druid.max-wait=3000
#是否缓存preparedStatement,也就是PSCache,PSCache对支持游标的数据库性能提升巨大,比如说oracle,在mysql下建议关闭。
spring.datasource.druid.pool-prepared-statements=false
#要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100
spring.datasource.druid.max-open-prepared-statements= -1
#配置检测可以关闭的空闲连接间隔时间
spring.datasource.druid.time-between-eviction-runs-millis=60000
# 配置连接在池中的最小生存时间
spring.datasource.druid.min-evictable-idle-time-millis= 300000
spring.datasource.druid.max-evictable-idle-time-millis= 400000
#监控统计的stat,以及防sql注入的wall
spring.datasource.druid.filters= stat,wall
#Spring监控AOP切入点,如x.y.z.service.*,配置多个英文逗号分隔
spring.datasource.druid.aop-patterns= com.web.springbootdruid.service.*
#是否启用StatFilter默认值true
spring.datasource.druid.web-stat-filter.enabled= true
#添加过滤规则
spring.datasource.druid.web-stat-filter.url-pattern=/*
#忽略过滤的格式
spring.datasource.druid.web-stat-filter.exclusions=*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*
#是否启用StatViewServlet默认值true
spring.datasource.druid.stat-view-servlet.enabled= true
#访问路径为/druid时,跳转到StatViewServlet
spring.datasource.druid.stat-view-servlet.url-pattern=/druid/*
# 是否能够重置数据
spring.datasource.druid.stat-view-servlet.reset-enable=false
# 需要账号密码才能访问控制台,默认为root
spring.datasource.druid.stat-view-servlet.login-username=root
spring.datasource.druid.stat-view-servlet.login-password=root
#IP白名单
spring.datasource.druid.stat-view-servlet.allow=127.0.0.1
# IP黑名单(共同存在时,deny优先于allow)
spring.datasource.druid.stat-view-servlet.deny=
原因:存入mysql数据丢失严重问题,批量建立新增连接,导致数据丢失问题。模拟一万条数据并未出现数据丢失问题。
1.针对非实时现实的数据,可以先批量存入mysql再查询出来,放入redis中,进行显示。 2.使用druid连接池,减少反复创建销毁。 3.使用Executors.newCachedThreadPool(),默认一分钟内线程无响应后,进行回收。