性能优化,定时批量入库支持类设计
并发量很高,在不引入中间件的情况下,自己写队列进行存储数据,然后定时批量获取,入库。
直接上代码,测试支持类:
import org.apache.commons.collections.CollectionUtils; import java.util.ArrayList; import java.util.List; import java.util.concurrent.LinkedBlockingQueue; import java.util.stream.Collectors; /** * <P> * 描述:批量插入支持,用於批量插入加到隊列,批量獲取 * </p> * * @author lishang Created on 2020/10/22 15:44 * @version 1.0 */ public class BatchSupport<T> { /** * 公用阻塞队列 */ private LinkedBlockingQueue<T> queue = new LinkedBlockingQueue(); /** * 将集合中的所有数据刷出 * @return */ public List<T> flush() { List<T> result=new ArrayList<>(); queue.drainTo(result); result=result.stream().filter(dto -> dto != null).collect(Collectors.toList()); return result; } /** * 批量插入List到缓冲对象中 * @param dtoList */ public void addList(List<T> dtoList) { if (CollectionUtils.isEmpty(dtoList)) { return; } queue.addAll(dtoList); } }
插入支持类:
import cn.hsa.ims.common.enums.TableName; import cn.hsa.ims.common.rdsutils.BatchOperation; import com.alibaba.fastjson.JSONArray; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; import java.util.List; /** * <P> * 描述:批量插入支持类 * </p> * * @author xxx Created on 2020/10/23 12:41 * @version 1.0 */ @Component public class BatchInsertSupport { private static final Logger LOGGER = LoggerFactory.getLogger(BatchInsertSupport.class); @Autowired @Qualifier("batchOption-adb") private BatchOperation batchOperationDrds; /** * 批量插入方法 * @param tableName * @param list */ public void batchInsert(TableName tableName, List<?> list){ if (list==null){ LOGGER.info("准备插入{},没有获取到数据,批量方法结束",tableName); return; } try { long start=System.currentTimeMillis(); batchOperationDrds.batchInsert(list, tableName.name(), 1000); long end=System.currentTimeMillis(); LOGGER.info("结束批量插入{}表记录条数:{},耗时:{}",tableName,list.size(),(end-start)); } catch (Exception e) { e.printStackTrace(); LOGGER.error("批量插入{}表异常,异常信息:{}",tableName, e.getMessage()); LOGGER.error("异常数据为:{},共{}条", JSONArray.toJSONString(list),list.size()); } } }
业务表flush方法和batchInsert方法:
/** * 批量插入 * * @param bffactWarnCallDTOS */ @Override public void batchInsert(List<BffactWarnCallDDTO> bffactWarnCallDTOS) { batchSupport.addList(bffactWarnCallDTOS); } /** * 将队列中的刷到数据库中 */ @Override public void flush() { List<BffactWarnCallDDTO> list = batchSupport.flush(); batchInsertSupport.batchInsert(TableName.BFFACT_WARN_CALL_D,list); }
定时任务处理:
Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { LOGGER.info("定时入库TimeTask.......Start"); xxxBO.flush(); LOGGER.info("定时入库TimeTask.......End"); } }, 1, 1000 * 60 * minutes);
整个处理流程大致如此,解决了批量入库耗时问题。
业务驱动技术,技术是手段,业务是目的。