在解决es入库问题上,之前使用过rest方式,经过一段时间的测试发现千万级别的数据会存在10至上百条数据的丢失问题,

在需要保证数据的准确性的场景下,rest方式并不能保证结果的准确性,因此采用了elasticsearch的BulkProcessor方式来进行数据入库,

实际上采用es客户端不同,rest方式采用的是restClient,基于http协议,BulkProcessor使用的是TransportClient,基于Tcp协议。

下面是在spring下具体的实现步骤:
1 定义一个student类,并json序列化
2 json的具体实现

3 构造BulkProcessor

* setBulkActions(1000):每添加1000个request,执行一次bulk操作
* setBulkSize(new ByteSizeValue(5, ByteSizeUnit.MB)):每达到5M的请求size时,执行一次bulk操作
* setFlushInterval(TimeValue.timeValueSeconds(5)):每5s执行一次bulk操作
* setConcurrentRequests(1):默认是1,表示积累bulk requests和发送bulk是异步的,其数值表示发送bulk的并发线程数,设置为0表示二者同步的
*setBackoffPolicy(BackoffPolicy.exponentialBackoff(TimeValue.timeValueMillis(100),3)):当ES由于资源不足发生异常
EsRejectedExecutionException重試策略:默认(50ms, 8),
* 策略算法:start + 10 * ((int) Math.exp(0.8d * (currentlyConsumed)) - 1)

package es;

import org.elasticsearch.action.bulk.BackoffPolicy;
import org.elasticsearch.action.bulk.BulkProcessor;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.unit.ByteSizeUnit;
import org.elasticsearch.common.unit.ByteSizeValue;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import java.net.InetAddress;
import java.net.UnknownHostException; @Configuration
public class ESConfiguration {
public static final Logger logger = LoggerFactory.getLogger(ESConfiguration.class); @Bean
public BulkProcessor bulkProcessor() throws UnknownHostException { Settings settings = Settings.builder().put("cluster.name", "elasticsearch").build(); Client client = new PreBuiltTransportClient(settings)
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("http://192.168.10.33"), Integer.parseInt("9300"))); return BulkProcessor.builder(client, new BulkProcessor.Listener() {
@Override
public void beforeBulk(long l, BulkRequest bulkRequest) { } @Override
public void afterBulk(long l, BulkRequest bulkRequest, BulkResponse bulkResponse) { } @Override
public void afterBulk(long l, BulkRequest bulkRequest, Throwable throwable) {
logger.error("{} data bulk failed,reason :{}", bulkRequest.numberOfActions(), throwable);
} }).setBulkActions(1000)
.setBulkSize(new ByteSizeValue(5, ByteSizeUnit.MB))
.setFlushInterval(TimeValue.timeValueSeconds(5))
.setConcurrentRequests(1)
.setBackoffPolicy(BackoffPolicy.exponentialBackoff(TimeValue.timeValueMillis(100), 3))
.build();
}
}

  

4. 入库代码实现

package es;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.elasticsearch.action.bulk.BulkProcessor;
import org.elasticsearch.action.index.IndexRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository; @Repository
public class StudentInsertDao{
private final Logger logger = LoggerFactory.getLogger(this.getClass()); @Autowired
private BulkProcessor bulkProcessor; private ObjectMapper objectMapper = new ObjectMapper(); public void insert(Student student) {
String type = student.getAge();
String id = student.getName()+student.getAddr()+student.getAge();
try {
byte[] json = objectMapper.writeValueAsBytes(student); bulkProcessor.add(new IndexRequest("students", type, id).source(json)); } catch (Exception e) {
logger.error("bulkProcessor failed ,reason:{}",e);
}
}
}

  

5. 测试代码

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = {"classpath:servlet-context.xml", "classpath:applicationContext.xml"})
public class StudentInsertDaoTest {
@Autowired
private StudentInsertDao insertDao; @Test
public void insert() throws Exception { Student student = new Student();
student.setAge(12);
student.setAddr("SH");
student.setName("Jack"); insertDao.insert(student);
}
}

  

原文链接:https://blog.csdn.net/wslyk606/article/details/79413980

Elasticsearch-BulkProcessor浅析:

https://blog.csdn.net/baichoufei90/article/details/97117025

elasticsearch使用BulkProcessor批量入库数据的更多相关文章

  1. Elasticsearch使用BulkProcessor批量插入

    https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-document-bulk. ...

  2. elasticsearch REST API方式批量插入数据

    elasticsearch REST API方式批量插入数据 1:ES的服务地址  http://127.0.0.1:9600/_bulk 2:请求的数据体,注意数据的最后一行记得加换行 { &quo ...

  3. discuz数据批量入库接口

    近期在做社区,首选discuz,数据需要用scrapy爬虫批量入库,就写了一个php入库接口. <?php define('PW', 'abc123456');//一定要修改 if($_REQU ...

  4. SqlBulkCopy 批量复制数据到数据表

    使用 SqlBulkCopy 类只能向 SQL Server 表写入数据.但是,数据源不限于 SQL Server:可以使用任何数据源,只要数据可加载到 DataTable 实例或可使用 IDataR ...

  5. SQLServer使用表值参数,高性能批量插入数据

    记得前段时间帮同事写了个解析账号并入库的小工具,来批量导入账号信息,账号量相当大,程序每读取一条记录便执行一次insert来插入数据,整整跑了一下午才把账号全部入库. 今天又接到同事类似的需求,不过这 ...

  6. 高并发简单解决方案————redis队列缓存+mysql 批量入库(ThinkPhP)

    问题分析 问题一:要求日志最好入库:但是,直接入库mysql确实扛不住,批量入库没有问题,done.[批量入库和直接入库性能差异] 问题二:批量入库就需要有高并发的消息队列,决定采用redis lis ...

  7. myBatis获取批量插入数据的主键id

    在myBatis中获取刚刚插入的数据的主键id是比较容易的 , 一般来说下面的一句话就可以搞定了 , 网上也有很多相关资料去查. @Options(useGeneratedKeys = true, k ...

  8. 转载:【高并发简单解决方案 | 靠谱崔小拽 】redis队列缓存 + mysql 批量入库 + php离线整合

    需求背景:有个调用统计日志存储和统计需求,要求存储到mysql中:存储数据高峰能达到日均千万,瓶颈在于直接入库并发太高,可能会把mysql干垮. 问题分析 思考:应用网站架构的衍化过程中,应用最新的框 ...

  9. redis 队列缓存 + mysql 批量入库 + php 离线整合

    问题分析 思考:应用网站架构的衍化过程中,应用最新的框架和工具技术固然是最优选择:但是,如果能在现有的框架的基础上提出简单可依赖的解决方案,未尝不是一种提升自我的尝试. 解决: 问题一:要求日志最好入 ...

随机推荐

  1. spark 机器学习 随机森林 原理(一)

    1.什么是随机森林顾名思义,是用随机的方式建立一个森林,森林里面有很多的决策树组成,随机森林的每一棵决 策树之间是没有关联的.在得到森林之后,当有一个新的输入样本进入的时候,就让森林中的每一棵决策树分 ...

  2. python之while循环用法举例,break与continue的区别,格式化输出及运算符

    一.while循环的基本结构 while 条件: 代码块(循环体) else: 当上面的条件为假. 才会执行 执行顺序:判断条件是否为真. 如果真. 执行循环体. 然后再次判断条件....直到循环条件 ...

  3. HTML&CSS基础-样式的继承

    HTML&CSS基础-样式的继承 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.HTML源代码 <!DOCTYPE html> <html> & ...

  4. Exchange 退信550 5.1.11 RESOLVER.ADR.ExRecipNotFound

    问题描述: 在Exchange 2013环境下,某客户将一个用户的邮箱test@abc.com禁用,过了几天又想连接该邮箱,但是却没有找到禁用的邮箱,然后客户就Enable-MailBox重新创建了一 ...

  5. 用js刷剑指offer(数组中的逆序对)

    题目描述 题目描述 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对1000000007取模的结果输出. 即输出P ...

  6. java 图片base64互转

    public class ImgBase64 { public static void main(String[] args) //测试 { String strImg = GetImageStr() ...

  7. Spring中Model,ModelMap和ModelAndView

    目录 1.Model接口 2.ModelMap 3.ModelAndView 1.Model接口(org.springframework.ui.Model) Model是一个接口,包含addAttri ...

  8. Machine learning system design---Error analysis

    Error analysis--让我们系统的去判断我们接下来要做什么,而不是随机的,凭直觉地选择一个去做 我们在设计机器学习应用时,刚开始使用简单(简单的features)的算法来很快的完成它,它可能 ...

  9. netty: 将传递数据格式转为String,并使用分隔符发送多条数据

    自定义分割符,用:DelimiterBasedFrameDecoder类 ByteBuf转String,用StringDecoder类 参考代码: //设置连接符/分隔符,换行显示 ByteBuf b ...

  10. AGC 030 B - Tree Burning 结论+枚举

    考试 T2,是一个脑筋急转弯. 最暴力的贪心是每次先选左,再选右,再选左..... 然而这么做在一些情况下是错的. 但是,我们发现我们的选法一定是 $LLLLRLRLRLRLR$ 或 $RRRRLRL ...