ES5.X批量索引一次实践

任务

将hbase中40亿的数据索引入ES5.x之中。

思路

对于这个任务,计划写一个jar包,用用消费者生产者模式多线程批量索引数据。

  1. 开一个读取数据的生产者线程,全表扫描hbase的源表。
  2. 将从hbase读取的数据解析后put到BlockingQueue中。
  3. 开启50个消防这线程,take BlockingQueue中的数据,调用ES 的bulk 批量索引API将数据索引入ES

问题

计划是美好的,过程是艰辛的,在运行程序的过程中遇到各种问题

问题1 内存溢出

由于ES5.X的配置中分配给ES的默认内存为2G,对于40亿的数据量,这点内存一定是不够的,因此需要提高内存到31g(网上建议不要超过32G)。

解决

打开ES安装目录下config/jvm.options文件 修改对应配置

-Xms2g => -Xms31g 
-Xmx2g => -Xmx31g 

问题2 [parent] Data too large, data for [] would be larger than…

对于这个问题首先的判断是断路器的阈值设置太低导致
修改elasticsearch.yml 中indices.breaker.total.limit 的值
发现,还是没有解决,只是延迟了报异常的时间
阈值已经提高到70%,也就是21.7G,然而还是包异常,也就是说批量索引的数据量超过了21.7G?
同时发现,索引的数据是生产的视觉的十几倍,而且这个倍数随着时间推移不断加大!知道ES挂掉。
那么估计是代码有问题。

while (true) {

             try {
                 MacIndexInfo macIndexInfo = blockingQueue.take();

                 XContentBuilder content = XContentFactory.jsonBuilder()
                         .startObject()
                        ...    //构建数据中              
                        .endObject();
                 String indexName = getIndexName(macIndexInfo.getCollect_time());
                 bulkRequest.add(this.client.prepareIndex(indexName, "type").setSource(content));
                 if (count % 10000 == 0) {
                     BulkResponse bulkResponse = bulkRequest.execute().actionGet();
                     if (bulkResponse.hasFailures()) {
                         System.out.println("threadName:" + Thread.currentThread().getName()+"  批量索引存在失败");
                     }
                                                                                }
                 count ++;
             } catch (Exception ex) {
                ex.printStackTrace();
             }

        }

这段代码就是问题所在,在while循环中不停的bulkRequest.add,然后满10000条提交一次。咋看没问题,但是每次提交之后 bulkRequest并没有清空数据,而是继续提交。
按这样的逻辑,第一次提交10000条数据,第二次提交20000条数据,依次类推。。这样不但重复索引数据,而且会在短时间内耗尽ES内存。
而且我看了一下网上的博客,很多都是没有清空数据的(好吧,我也是参考网上代码的)。

解决

“`
while (true) {

         try {
             MacIndexInfo macIndexInfo = blockingQueue.take();

             XContentBuilder content = XContentFactory.jsonBuilder()
                     .startObject()
                    ...    //构建数据中              
                    .endObject();
             String indexName = getIndexName(macIndexInfo.getCollect_time());
             bulkRequest.add(this.client.prepareIndex(indexName, "type").setSource(content));
             if (count % 10000 == 0) {
                 BulkResponse bulkResponse = bulkRequest.execute().actionGet();
                 if (bulkResponse.hasFailures()) {
                     System.out.println("threadName:" + Thread.currentThread().getName()+"  批量索引存在失败");
                 }
          bulkRequest = client.prepareBulk();                                                                       }
             count ++;
         } catch (Exception ex) {
            ex.printStackTrace();
     ace });
  }

只需提交完后重新获取即可bulkRequest

你可能感兴趣的:(ES5.X批量索引一次实践)