06|向ES批量写入数据

238 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第10天,点击查看活动详情

1.批量写入数据

在上一小节我们写完了造数据的工具类,接下来我们向E S里边插入100W条假数据,用来做后边的一些api的操作。

在实际生产当中,当我们有大量的数据需要写入ES时候,如果数据可以聚合起来,我们一般采用批量写入的方式,就是采用es的_bulk方法写入数据,可以预先把数据想放到一个缓存里边,当里边的数据达到一定量的时候,将数据刷入es,然后清空缓存,在接收数据,继续写入。

在进行写入数据这个过程中,我们可以采用多线程的方式提高数据的写入效率。

es写入数据.drawio.png

2.编写批量写入程序

我们在service新增方法写入数据

     /**
      * 造假数据
      */
     void mockData();

这个方法的具体实现如下

@Override
    public void mockData() {
        ExecutorService executorService = Executors.newFixedThreadPool(5);

        //原子类
        AtomicLong id = new AtomicLong();
        //已经插入的
        AtomicLong inserted = new AtomicLong();

        for (int i = 0; i < 5; i++) {
            log.info("开始多线程插入数据");
            executorService.submit(() -> {
                List<GoodsItemReq> list = new ArrayList<>();
                for (int j = 0; j < 200000; j++) {
                    GoodsItemReq goodsItemReq = fillData(id);
                    list.add(goodsItemReq);
                    if (list.size() == 2000) {
                        bulkInsertGoods(list);
                        log.info("插入ES完成");
                        list.clear();
                        inserted.addAndGet(2000L);
                        log.info("已经插入了[{}]条数据",inserted.get());
                    }
                }
            });
        }
        executorService.shutdown();
    }

    private GoodsItemReq fillData(AtomicLong id) {
        GoodsItemReq goodsItemReq = new GoodsItemReq();

        goodsItemReq.setId(id.incrementAndGet());
        goodsItemReq.setCategory(MockDataUtil.getMockValue(GoodsEnums.CATEGORY));
        goodsItemReq.setBasePrice(MockDataUtil.getPrice());
        goodsItemReq.setMarketPrice(MockDataUtil.getPrice());
        goodsItemReq.setStockNum(MockDataUtil.getStockNum());
        goodsItemReq.setSkuId(MockDataUtil.getMockValue(GoodsEnums.SKUID));
        goodsItemReq.setSkuImgUrl(MockDataUtil.getMockValue(GoodsEnums.SKUIMGURL));
        goodsItemReq.setSkuName(MockDataUtil.getMockValue(GoodsEnums.SKUNAME));
        try {
            goodsItemReq.setCreateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(MockDataUtil.getMockValue(GoodsEnums.CREATETIME)));
            goodsItemReq.setUpdateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(MockDataUtil.getMockValue(GoodsEnums.UPDATETIME)));
        } catch (ParseException e) {
            log.error(e.getMessage(), e);
        }

        return goodsItemReq;
    }

controller里边调用service的方法

    @PostMapping("/mockdata")
    @ResponseBody
    private BaseResponse<Void> mockdata() {
        goodsService.mockData();
        return new BaseResponse<>();
    }

接下来启动项目,进行数据的生成,通过postman进行数据的生成

curl --location --request POST 'http://localhost:8089/goods/mockdata'

3.验证数据是否正确生成

在kibana界面我们在dev tools面板,通过如下命令查看数据是否生成了100W条

 GET goods_item_index/_count
 {
   "query": {
     "match_all": {
      
     }
   }
 }

查询结果如下所示

 {
   "count": 1000000,
   "_shards": {
     "total": 3,
     "successful": 3,
     "skipped": 0,
     "failed": 0
   }
 }

然后我们再通过如下命令,查几条数据,看下生成的详情数据

可以看到"count"对应的数字是100W。

 GET goods_item_index/_search
 {
   "query": {
     "match_all": {
       
     }
   }
 }

查询结果如下所示

image-20221121223057829.png