在解决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. flask-sqlalchemy用法详解

    一. 安装 $ pip install flask-sqlalchemy 二. 配置 配置选项列表 : 选项 说明 SQLALCHEMY_DATABASE_URI 用于连接的数据库 URI .例如:s ...

  2. c# 使用泛型集合List<T>

  3. 虚拟机搭建IKUAI软路由

    1.登录爱快软路由的官网下载镜像(支持ISO ,GHO),这里采用iso安装 2.选择好后开机(选择数字编号1,回车) 3.输入“y”回车,程序自动安装 4.安装成功后如图 5.设置IP 6.绑定网卡 ...

  4. Flink原理(七)——动态表(Dynamic tables)

    前言 本文是结合Flink官网,个人理解所得,若是有误欢迎留言指出,谢谢!文中图皆来自官网(链接[1]). 本文将随着下面这个问题展开,针对该问题更为生动的解释可以参见金竹老师的分享(链接[2]). ...

  5. XML DOM 知识点

    第一部分[DOM基础] DOM介绍: 1.什么是 HTML DOM? HTML DOM 定义了所有 HTML 元素的对象和属性,以及访问它们的方法(接口). 2.什么是 XML DOM? XML DO ...

  6. xinetd配置文件

    xinetd是一个超级守护进程xinetd即extended internet daemon,xinetd是新一代的网络守护进程服务程序,又叫超级Internet服务器.经常用来管理多 种轻量级Int ...

  7. HDU2870 Largest Submatrix

    Largest Submatrix Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  8. 应该知道的linux命令

    常用命令 1.在compose Bar下可以对多个服务器同时进行操作.选择To All Sessions 2. 查看JAVA进程: ps -ef | grep java ps auxf | grep ...

  9. Mac上django 报错 [Errno 13] Permission denied: '/static'

    将setting文件中的 改成:

  10. 多线程实现的方式一继承Thread

    实现方法一:继承Thread类 package thread; /** * @function 多线程继承Thread类 * @author hj */ public class Threads ex ...