Bootstrap

多线程批量导入数据到es

一、说明

使用线程池导入mysql数据到ElasticSearch效率极高

平均速度30s,测试数据88000条

正常遍历导入需要花费20分钟

创建线程池:需要必要参数(核心线程数、最大线程数、线程持续时间、空闲线程最大存活时间、时间单位、阻塞队列、拒绝策略)

拒绝策略有四种: 这里使用第三个

  • ThreadPoolExecutor.AbortPolicy

        丢弃任务并抛出RejectedExecutionException异常,默认策略

  • DiscardPolicy

        丢弃任务,不抛异常

  • DiscardOldestPolicy

        抛弃队列中等待最久的任务(队列第一个)然后把当前任务加入队列中

  • CallerRunsPolicy

        调用任务的 run()方法绕过线程池直接执行

二、 代码

@SpringBootTest
@RunWith(SpringRunner.class)
@Slf4j
public class InjectData {
    @Autowired
    private RestHighLevelClient esClient;
    @Autowired
    private ItemClient itemClient;

    //多线程导入es
    @Test
    public void injectDataByThread() throws IOException {
        //创建线程池
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 10, 60,
                TimeUnit.SECONDS, new ArrayBlockingQueue<>(3),
                new ThreadPoolExecutor.DiscardOldestPolicy());
        //查询总条数
        Integer total = itemClient.itemCount();
        //计算总页数
        int pages = (int) Math.ceil((double) total / 10000);
        //分页导入数据
        for (int page = 1; page <= pages; page++) {
            PageDTO<Item> dto = itemClient.itemPage(page, 10000);
            if (dto.getList() != null && dto.getList().size() > 0) {
                //
                threadPool.execute(new Runnable() {
                    @Override
                    public void run() { //加入到线程池任务
                        try {
                            //创建request对象
                            BulkRequest bulkRequest = new BulkRequest();
                            //遍历每条数据转换为es实体
                            for (Item item : dto.getList()) {
                                ItemDoc itemDoc = new ItemDoc(item);
                                //转为json配置indexRequest对象添加请求
                                IndexRequest indexRequest = new IndexRequest("hmall")
                                        .id(itemDoc.getId().toString())
                                        .source(JSON.toJSONString(itemDoc), XContentType.JSON);
                                bulkRequest.add(indexRequest);
                            }
                            esClient.bulk(bulkRequest, RequestOptions.DEFAULT);
                            log.info("【es】thread:{},msg:本次同步 {} 条数据",
                                    Thread.currentThread().getName(), dto.getList().size());
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
            try {
                //延迟3秒等elasticsearch完成写入数据
                Thread.sleep(3000L);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
;