使用多线程推松数据到ES中,无数据丢失

ES作为缓存,越来越流行,使用多线程推送数据方案

public void bulkImportAll(String year,Integer source){
		//初始化线程池,
        ThreadPoolExecutor executor = new ThreadPoolExecutor(16, 32, 20, TimeUnit.MILLISECONDS,
                new ArrayBlockingQueue<>(1024), new ThreadPoolExecutor.CallerRunsPolicy());
        int count = orderDao.selectOrderCount(StringUtils.isEmpty(year)?DateUtil.getYear():year,source);
		//每个线程发配的任务数
        int size = 1000;
        //需要查询次数
        int times = count / size;
        if (count % size != 0) {
            times = times + 1;
        }
        for (int i = 0; i < times; i++) {
            BatchSelectOrder batchSelectOrder = new BatchSelectOrder(source,year,i,size,restHighLevelClient,orderDao,orderItemDao);
            executor.execute(batchSelectOrder);
            log.info("线程池中线程数目:{} ,队列中等待执行的任务数目:{} ,已执行完的任务数目:{}" , executor.getPoolSize(),executor.getQueue().size(),
                    executor.getCompletedTaskCount());
        }
        executor.shutdown();
    }


@Slf4j
public class BatchSelectOrder implements Runnable {


    private static String indexName="order_es_analyse";

    private int bindex;//当前页数

    private int size;//每页查询多少条

    private String year ;//年份

    private Integer source ;//卖场

    private RestHighLevelClient restHighLevelClient;

    private OrderDao orderDao;

    private OrderItemDao orderItemDao;


    public BatchSelectOrder(int bindex, int size) {
        this.bindex = bindex;
        this.size = size;
    }

    public BatchSelectOrder(Integer source,String year,int bindex, int size, RestHighLevelClient restHighLevelClient, OrderDao orderDao, OrderItemDao orderItemDao) {
        this.source = source;
        this.year = year;
        this.bindex = bindex;
        this.size = size;
        this.restHighLevelClient = restHighLevelClient;
        this.orderDao = orderDao;
        this.orderItemDao = orderItemDao;
    }

    
    public void batchSelectOrders() {
        log.info("begin start batch select task....");
        //查询主表数据
        List<OrderAnalyzes> ordersByYear = orderDao.findOrdersByYear(StringUtils.isEmpty(year)?DateUtil.getYear():year,source,bindex* size, size);
        if (CollectionUtils.isNotEmpty(ordersByYear)){
            ordersByYear.forEach(c-> {
                  //查询子表数据
                List<OrderItemAnalyzes> orderItems = orderItemDao.findOrderItemByOrderId(StringUtils.isEmpty(year)?DateUtil.getYear():year, c.getTradeId());
                c.setOrderItemEntityList(orderItems);
            });
            List<OrderESEntity> orderEsEntities =new ArrayList<>();
                //处理数据,把查询到数据赋值到ES的实体类中
            ordersByYear.forEach(c->{
                OrderESEntity orderEsEntity =new OrderESEntity();
                exchangeEs(StringUtils.isEmpty(year)?DateUtil.getYear():year,c,orderEsEntity);
                orderEsEntities.add(orderEsEntity);
            });
            //创建两个请求,第一个请求用来添加数据,第二个请求用来删除数据
            BulkRequest bulkRequest = new BulkRequest();
            BulkRequest bulkRequestForDel = new BulkRequest();

            orderEsEntities.forEach(v->{
                if(v.getDeleted()){
                    DeleteRequest deleteRequest = new DeleteRequest(indexName,v.getId());
                    bulkRequestForDel.add(deleteRequest);
                }else{
                    IndexRequest indexRequest=new IndexRequest(indexName);
                    indexRequest.id(v.getId()).source(JSON.toJSONString(v), XContentType.JSON);
                    bulkRequest.add(indexRequest);
                }
            });
            restHighLevelClient.bulkAsync(bulkRequest, RequestOptions.DEFAULT,new ActionListener<BulkResponse>() {
                @Override
                public void onResponse(BulkResponse bulkResponse) {
                    log.info("批量写入es成功");
                }
                @Override
                public void onFailure(Exception e) {
                    //出错的时候调用
                    log.info("批量写入es错误:"+e.getMessage());
                }
            });
            if(bulkRequestForDel.requests().size()>0){
                restHighLevelClient.bulkAsync(bulkRequestForDel, RequestOptions.DEFAULT, new ActionListener<BulkResponse>() {
                    @Override
                    public void onResponse(BulkResponse bulkItemResponses) {
                        log.info("按照id批量删除部分数据成功");
                    }

                    @Override
                    public void onFailure(Exception e) {
                        log.info("按照id批量删除部分数据失败:"+e.getMessage());
                    }
                });
            }

            log.info("end batch select task....");
        }
    }



    @Override
    public void run() {
        batchSelectOrders() ;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
利用Java多线程技术导入数据Elasticsearch的方法步骤如下: 步骤1:引入必要的依赖 首先,需要在项目引入ElasticsearchJava客户端依赖,可以通过Maven或Gradle进行引入。 步骤2:创建Elasticsearch客户端 使用ElasticsearchJava客户端创建与Elasticsearch服务器的连接。可以使用TransportClient或RestClient来进行连接。 步骤3:创建数据导入任务 创建一个数据导入任务类,实现Runnable接口,并重写run()方法。该任务类负责将数据导入到Elasticsearch。根据需求,可以将数据分批导入,也可以按照一定规则并发导入。 步骤4:创建线程池 创建一个线程池,用于管理多个线程执行数据导入任务。可以使用Java自带的ThreadPoolExecutor类来创建线程池,并根据需求设置线程池的大小、任务队列等相关参数。 步骤5:提交任务到线程池 将数据导入任务提交到线程池执行。可以使用execute()方法提交任务,也可以使用submit()方法提交任务并获取返回结果。 步骤6:等待任务完成 使用CountDownLatch或其他同步工具等待所有的数据导入任务完成。可以通过调用shutdown()方法关闭线程池,并在主线程调用awaitTermination()方法等待所有任务执行完成。 步骤7:关闭Elasticsearch客户端 在数据导入完成后,关闭与Elasticsearch服务器的连接,释放资源。 步骤8:处理导入结果 根据需要,可以在任务类添加相应的处理逻辑,比如统计导入数据的成功和失败数量,打印异常信息等。 总结: 利用Java多线程技术导入数据Elasticsearch的主要步骤包括引入依赖、创建Elasticsearch客户端、创建数据导入任务、创建线程池、提交任务到线程池、等待任务完成、关闭客户端和处理导入结果。根据具体需求,可以灵活调整以上步骤的顺序和细节。同时,还应注意线程安全和异常处理等问题,以保证数据导入的正确性和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值