ElasticSearch批量处理器

其实之前在ElasticSearch之Java API就有提到过批量处理器,它可以把多个请求放在bulk缓存集中处理,大大减少了ES的网络连接,实在是优化ES性能的神兵利器!

如何使用

首先创建一个BulkProcessor:

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.transport.TransportClient;
import org.elasticsearch.common.unit.ByteSizeUnit;
import org.elasticsearch.common.unit.ByteSizeValue;
import org.elasticsearch.common.unit.TimeValue;

public class EsBulkDatasource  {
	/**
	 * bulkProcessor
	 */
	private BulkProcessor bulkProcessor = null;
	
	/**
	 * @return BulkProcessor
	 */
	public BulkProcessor getInstance() {
		return bulkProcessor;
	}
	
	/**
	 * @param client
	 * @param batchNum
	 * @param flushInterval
	 */
	public EsBulkDatasource(TransportClient client, int batchNum, int flushInterval) {
		bulkProcessor = BulkProcessor.builder(
		client, // 添加你的客户端
		new BulkProcessor.Listener() {
			
			// 在批量执行之前调用此方法,可以查看numberOfActions
			public void beforeBulk(long executionId, BulkRequest request) {
				System.out.println(request.numberOfActions());
			}
			
			// 当批量执行引发异常时,调用此方法
			public void afterBulk(long executionId, BulkRequest request, Throwable failure) {
				
			}
			
			// 批量执行之后调用此方法,可以检查是否存在一些失败的请求
			public void afterBulk(long executionId, BulkRequest request, BulkResponse response) {
				System.out.println(response.hasFailures());
			}
		})
		.setBulkActions(batchNum) // 每10000个请求执行批量处理。默认值:1000
		.setBulkSize(new ByteSizeValue(5,ByteSizeUnit.MB)) // 每5M冲洗一次数据。默认值:5mb
		.setFlushInterval(TimeValue.timeValueSeconds(flushInterval)) // 无论请求数量多少,我们都希望每5秒刷新一次。默认值:无
		.setConcurrentRequests(10) // 设置并发请求数。0 只允许执行单个请求,1 允许执行1个请求,同事累积新的批量请求。默认值:1(这意味着异步执行刷新操作)
		
		// 设置自定义退避策略,该策略最初等待100毫秒,以指数方式增加并重试最多三次。
		//每当一个或多个批量项目请求失败时,尝试重试,EsRejectedExecutionException这表示可用于处理请求的计算资源太少。
		//要禁用退避策略,设置BackoffPolicy.noBackoff()
		// 默认值:重试次数8次,启动延迟50ms。总等待5.1秒。
		.setBackoffPolicy(
				BackoffPolicy.exponentialBackoff(TimeValue.timeValueMillis(100), 3)) 
		.build();

	}
}

批量处理器工厂类:

public class BaseBulkRepository<T> {
	
	/**
	 * bulkDatasource
	 */
	private EsBulkDatasource bulkDatasource;
	/**
	 * 构造参数
	 * @param bulkDatasource
	 */
	public BaseBulkRepository(EsBulkDatasource bulkDatasource) {
		this.bulkDatasource = bulkDatasource;
	}
	
	public void save(String index, String type, T entity, String id) {
		String source = JsonUtil.toJson(entity);
		bulkDatasource.getInstance().add(new IndexRequest(index, type, id).source(source));
	}
	
	public void remove(String index, String type, String id) {
		bulkDatasource.getInstance().add(new DeleteRequest(index, type, id));
	}
}

创建具体业务模块的批量处理器:

public class HistoryIndexBulkRepository extends BaseBulkRepository<Entity> {

	public HistoryIndexBulkRepository(EsBulkDatasource bulkDatasource) {
		super(bulkDatasource);
	}

}

配置bean声明在xml中:

<elasticsearch:transport-client id="esClient" cluster-nodes="你的es节点" cluster-name="你的es节点名"/>

<bean name="bulkDatasource" class="cn.my.EsBulkDatasource" scope="singleton">
    	<constructor-arg name="client" ref="esClient"/>
    	<constructor-arg name="batchNum" value="20000" />
    	<constructor-arg name="flushInterval" value="5" />
    </bean>

<bean name="historyIndexBulkRepository" class="cn.my.HistoryIndexBulkRepository">
    	<constructor-arg name="bulkDatasource" ref="bulkDatasource"/>
    </bean>

最后调用批量处理器:

@Autowired
private HistoryIndexBulkRepository historyIndexBulkRepository;

historyIndexBulkRepository.save(ES_INDEX, ES_TYPE, entity, entity.getId());

小结

批量处理器有利有弊,好处很明显,能提高性能。弊端就是数据不是实时存储在ES库中的,如果对于实时性要求比较敏感,则建议根据自身业务酌情选择。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值