Spark写入ES优化

Spark写入ES优化

Spark写入ES方案

1.写入demo,详情看官网- Elasticsearch for Apache Hadoop

写入性能优化

  1. 给filesystem cache更多的内存
  • filesystem cache被用来执行更多的IO操作,如果我们能给filesystemcache更多的内存资源,那么es的写入性能会好很多。
  1. 用bulk批量写入
  • 你如果要往es里面灌入数据的话,那么根据你的业务场景来,如果你的业务场景可以支持让你将一批数据聚合起来,一次性写入es(比如:离线的方式),那么就尽量采用bulk的方式,每次批量写个几百条这样子。
  • bulk批量写入的性能比你一条一条写入大量的document的性能要好很多。但是如果要知道一个bulk请求最佳的大小,需要对单个es node的单个shard做压测。先bulk写入100个document,然后200个,400个,以此类推,每次都将bulk size加倍一次。如果bulk写入性能开始变平缓的时候,那么这个就是最佳的bulk大小。并不是bulk size越大越好,而是根据你的集群等环境具体要测试出来的,因为越大的bulk size会导致内存压力过大,因此最好一个请求不要发送超过10mb的数据量。
  • 先确定一个是bulk size,此时就尽量是单线程,一个es node,一个shard,进行测试。看看单线程最多一次性写多少条数据,性能是比较好的。
  1. 使用多线程将数据写入es
  • 单线程发送bulk请求是无法最大化es集群写入的吞吐量的。如果要利用集群的所有资源,就需要使用多线程并发将数据bulk写入集群中。为了更好的利用集群的资源,这样多线程并发写入,可以减少每次底层磁盘fsync的次数和开销。首先对单个es节点的单个shard做压测,比如说,先是2个线程,然后是4个线程,然后是8个线程,16个,每次线程数量倍增。一旦发现es返回了TOO_MANY_REQUESTS的错误,JavaClient也就是EsRejectedExecutionException。此时那么就说明es是说已经到了一个并发写入的最大瓶颈了,此时我们就知道最多只能支撑这么高的并发写入了。
  1. 增加refresh间隔
  • 默认情况下写入到es的数据并不是马上就刷到磁盘,先放在 in-memory buffer,但客户端是读取不到in-memory buffer中的数据,为了实时查询,需要定期(默认1s)将该数据刷写到介于es和磁盘之间的filesystem cache 即refresh,该操作轻量级的。
  • 写入到filesystem cache相当于创建新的segment 是可以被客户端读取到的, 默认属性(阈值是1s)由于快速的刷数据导致很多小量的filesystem cache,同时写入到filesystem cache仍然有一些性能消耗,所以根据应用的使用场景,如果是关注写入速度并不关注实时查询,可以适当调整默认的阈值的,该属性是在创建索引(属性值为:index.refresh_interval)的时候设置的,官网参数-near-real-time
  1. 关闭WAL事务日志
  • 关闭事务日志WAL,也可以提升性能,不过可能造成丢数据
  1. 其他优化
  • 不需要分词的String字段可以将字段类型设置为keyword
  • 让es自动生成id(业务中的表id,可以作为es document的一个field);不过这样不能保证幂等
  • 根据es集群的配置调整合适的shard num
  • spark写入是否存在数据倾斜以保证分布式计算的集群的优势

案例

案例:使用Spark将Hive的数据同步到ES

常用优化策略

  1. bulk批量写入
  • 说明:采用的es-spark模块来写的,好处时:hive->spark->es的pipeline流程,spark底层也是使用的bulkProcesser来操作的,相关bulk参数自己调
  • 参数:参数设置参考官网-configuration
SparkSession spark = SparkSession.builder()
		.config("es.batch.size.entries", "5000")//设置批写入的bulk数量,默认1000条
		.config("es.batch.size.bytes", "2.5mb")//设置批写入的bulk大小(设置小于10Mb),默认1Mb;和上面参数协作,两者谁先满足,则触发bulk write
		.config("es.batch.write.refresh", "false")//关闭批写入后主动刷新索引的操作,默认是true
		.enableHiveSupport()
		.getOrCreate();
  1. 使用多线程将数据写入es
  • 说明:spark多个task线程来跑,具体spark-submit后的参数(如:excutor数量、内存、cpu根据情况调节)
  • 参数:比如增加spark程序的executor数量等
  1. 增加refresh间隔
  • 说明1:如果不需要实时查询ES数据的话,可以在index setting处调大或者关闭refresh、同步完之后再手动调用一次Refresh接口
  • 说明2:性能提升关键再与不用频繁Refresh
  • 参数:
		//关闭refresh
		Settings settings = Settings.builder()
        //refresh刷新时间,默认1s;设置为-1表示关闭
        .put("index.refresh_interval", "-1")
        .build();
		//手动调用Refresh
		RefreshRequest refreshRequest = new RefreshRequest(index);
		client.indices().refresh(refreshRequest, RequestOptions.DEFAULT);
  1. 其他的优化
  • 如果可靠性、一致性要求不高的场景、可以选择关闭WAL事务日志;使用自动生成的id(不保证幂等性的)
  • 不分词的部分,比如:String类型,可以按照keyword来存的
  • 调整分片数也能提高写入性能,不过得注意改了分片后可能导致之前的数据找不到(查找过程:按照docId的hash值,之后根据分片数来hash的吧);看具体场景修改
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值