任务
将hbase中40亿的数据索引入ES5.x之中。
思路
对于这个任务,计划写一个jar包,用用消费者生产者模式多线程批量索引数据。
- 开一个读取数据的生产者线程,全表扫描hbase的源表。
- 将从hbase读取的数据解析后put到BlockingQueue中。
- 开启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