ES的写入速度优化
1、tranlog flush 间隔调整
默认设置下,每个请求都flush,这是影响es写入速度的最大因素,需要调整translog持久化策略为周期性和一定大小的时候flush,例如:
index.translog.durability: async
设置为async表示translog的刷盘策略按sync_interval配置指定的时间周期进行。
index.translog.sync_interval:120s
加大translog刷盘间隔时间。默认5s,不低于100ms.
index.translog.flush_threshold_size: 1024mb
超过这个大小导致refresh,默认512MB
2、并发执行bulk请求
单线程发送bulk请求是无法最大化es集群写入的吞吐量的。如果要利用集群的所有资源,就需要使用多线程并发将数据bulk写入集群中。为了更好的利用集群的资源,这样多线程并发写入,可以减少每次底层磁盘fsync的次数和开销。首先对单个es节点的单个shard做压测,比如说,先是2个线程,然后是4个线程,然后是8个线程,16个,每次线程数量倍增。一旦发现es返回了TOO_MANY_REQUESTS的错误,JavaClient也就是EsRejectedExecutionException。此时那么就说明es是说已经到了一个并发写入的最大瓶颈了,此时我们就知道最多只能支撑这么高的并发写入了。
3、增加refresh interval
默认的refresh间隔是1s,用index.refresh_interval参数可以设置,这样会其强迫es每秒中都将内存中的数据写入磁盘中,创建一个新的segment file。正是这个间隔,让我们每次写入数据后,1s以后才能看到。但是如果我们将这个间隔调大,比如30s,可以接受写入的数据30s后才看到,那么我们就可以获取更大的写入吞吐量,因为30s内都是写内存的,每隔30s才会创建一个segment file。
4、磁盘间的任务均衡
- 简单轮询:在系统初始阶段,简单轮询的效果是最均匀的。
- 基于可用空间的动态加权轮询:以可用空间作为权重,在磁盘之家加权轮询。
5、节点间的任务均衡
为了节点间的任务尽量均衡,数据写入客户端应该把bulk请求轮询发送到各个节点。
6、调整字段Mappings
-
减少字段数量,不需要建立索引的字段,不写入ES
-
将不需要建立索引的字段index属性设置not_analyed或no
-
减少字段内容长度
-
使用不同的分析器
7、使用自动生成的id
如果我们要手动给es document设置一个id,那么es需要每次都去确认一下那个id是否存在,这个过程是比较耗费时间的。如果我们使用自动生成的id,那么es就可以跳过这个步骤,写入性能会更好。对于你的业务中的表id,可以作为es document的一个field。
8、段合并优化
merge策略默认用的tiered,但是可以对策略的参数进行一些调整。如果堆栈经常有很多merge,则可以尝试调整以下策略配置:
index.merge.policy.segments_per_tier
取值越小则最终segment越少,因此需要merge的操作更多,可以考虑增加此值,默认为10,应该大于等于index.merge.policy.max_merge_at_once
。
9、indexing buffer
如果我们要进行非常重的高并发写入操作,那么最好将index buffer调大一些,这和可用堆内存、单节点上的shard数量相关,indices.memory.index_buffer_size,这个可以调节大一些,设置的这个index buffer大小,是所有的shard公用的,但是如果除以shard数量以后,算出来平均每个shard可以使用的内存大小,一般建议,但是对于每个shard来说,最多给512mb,因为再大性能就没什么提升了。es会将这个设置作为每个shard共享的index buffer,那些特别活跃的shard会更多的使用这个buffer。默认这个参数的值是10%,也就是jvm heap的10%,如果我们给jvmheap分配10gb内存,那么这个index buffer就有1gb,对于两个shard共享来说,是足够的了。
10、禁用_all字段
禁止_all字段可以明显降低对CPU和I/O的压力。