ElasticSearch 批量插入漏数据

项目场景:

项目中需要把Mysql数据同步到ElasticSearch中


问题描述

数据传输过程中数据不时出现丢失的情况,偶尔会丢失一部分数据,本地测试也无法复现,后台程序也没有报错,一到正式环境就有问题,很崩溃

这里是批量操作的代码

java 复制代码
private void bulk(List<IndexRequest> indexRequests) throws Exception {
        try {
            // 在这里可以对你获取到的批量结果数据进行需要的业务处理
            BulkProcessor bulkProcessor = BulkProcessor.builder(
                            (req, bulkListener) -> restHighLevelClient.bulkAsync(req, RequestOptions.DEFAULT, bulkListener),
                            new BulkProcessor.Listener() {
                                private int totalCount = 0;

                                @Override
                                public void beforeBulk(long executionId, BulkRequest request) {
                                }

                                @Override
                                public void afterBulk(long executionId, BulkRequest request, BulkResponse response) {
                                    // 统计条数并输出信息
                                    int count = response.getItems().length;
                                    totalCount += count;
                                    log.info("批量操作 [{}] 成功执行了{}条请求,共处理了{}条数据", executionId, count, totalCount);
                                }

                                @Override
                                public void afterBulk(long executionId, BulkRequest request, Throwable failure) {
                                    log.error("数据处理失败,执行id为{},错误信息为:{}", executionId, failure);
                                }
                            }
                    )
                    .setConcurrentRequests(esproperties.getThreadSize())/*并发请求的数量。默认为1。*/
                    .setFlushInterval(TimeValue.timeValueSeconds(30)) // 固定30s必须刷新一次
                    .setBulkSize(new ByteSizeValue(10L, ByteSizeUnit.MB)) // 5MB batch size
                    .setBulkActions(esproperties.getBulkActions()) // 每次执行最多处理5000个请求
                    .setBackoffPolicy(BackoffPolicy.exponentialBackoff(TimeValue.timeValueMillis(100), 3))
                    .build();
            indexRequests.forEach(bulkProcessor::add);
            bulkProcessor.close();
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception(e);
        }
    }

原因分析:

当时想到的问题是这里是不是数据格式有问题,因为采用的是异步,就是错误了也不会影响到其它数据的插入

接着就定位到了这段代码,想想是不是哪里没有处理错误的数据信息,所以没有打印出来,果然发现了BulkResponse 这个类,是可以处理每个错误信息的,接着就优化了代码如下

其实只需要修改afterBulk 方法,遍历出现的异常就能够打印出导入不进去的错误信息

java 复制代码
 @Override
public void afterBulk(long executionId, BulkRequest request, BulkResponse response) {
 // 统计条数并输出信息
// int count = response.getItems().length;
// totalCount += count;
//  log.info("批量操作 [{}] 成功执行了{}条请求,共处理了{}条数据", executionId, count, totalCount);
 if (response.hasFailures()){
     for (BulkItemResponse itemResponse : response) {
         if (itemResponse.isFailed()) {
             log.info("数据写入失败:错误信息为:{}",itemResponse.getFailureMessage());
         }
     }
// log.info("数据写入失败:{}",response.buildFailureMessage());
 }
}

解决方案:

接着修改代码后把新的包放上去,执行,终于找到了错误信息

下面是错误信息的截图

报错 Limit of total fields 1000 这里就能看出来,是字段数量大于1000了,因为我的是宽表,而之前创建的索引字段数量都是小于1000的,新的索引结构数量大于1000,找到问题就好办了

在kibana执行下面脚本修改字段限制,根据实际情况来,没有kibana就写出curl 请求

ruby 复制代码
PUT 你的索引名/_settings
{
  "index": {
    "mapping.total_fields.limit": 2000
  }
}

总结

  1. 没有测试好宽表字段比较多的情况
  2. 写代码的时候以为很简单不会出现问题,所以日志也比较随便。
  3. 日常开发要打印好日志,它能够在出现错误的情况下,很快的帮我们定位出问题所在。
相关推荐
Rider_bai9 分钟前
长春到天津物流专线,长春到天津物流公司,如何找到靠谱公司的联系方式?
大数据·网络·物联网·敏捷流程·交通物流
团象科技25 分钟前
从一线实操案例拆解不同出海团队落地海外VPS运维独立站的路径细节
大数据·数据库·人工智能
yinmaisoft26 分钟前
JNPF 三大主流行业解决方案,按需定制
大数据·低代码·开发工具
王牌狮AIen1 小时前
AI营销智能体实战:OPC如何重构自主获客闭环?
大数据·人工智能·重构·数据挖掘·geo·ai营销
上海达策TECHSONIC1 小时前
零售ERP选型解析:SAP Business One 适配成长型零售企业的核心逻辑
大数据·运维·人工智能·云计算·运维开发·零售
大大大大晴天️1 小时前
Hudi技术内幕:Query Types全解析
大数据·hudi
serve the people2 小时前
Elasticsearch(5) i want to monitor the es health from a http api
大数据·http·elasticsearch
2601_959477912 小时前
Vatee:外汇行情信息呈现与技术架构如何影响体验,给出一套细节
大数据·人工智能·安全·ux
Kepler18742 小时前
注射器与输液器厂分布在哪里?全国主要产区梳理
大数据·其他
萤丰信息2 小时前
存量焕新 + 绿色低碳,2026 智慧园区转型新路径
大数据·人工智能