Elasticsearch写入优化

南墨1年前技术文章504

1.1 基本优化手段

Elasticsearch默认的设置和参数配置下,是综合考虑了数据的可靠性、搜索实时性、写入速度等因素。但在安平实际场景中,业务对数据的可靠性和搜索实时性要求并不高,反而对写入速度要求高,可以通过调整一些策略,优化写入速度。

综合来说,提升写入速度可以从以下几个方面入手:

1.       加大index refresh间隔,除了降低IO,更重要的是降低了segment merge的频率;

2.       加大translog refresh间隔,目的是降低iopswriteblock

3.       调整bulk请求,控制每次bulk请求提交的量;

4.       优化磁盘间的任务均匀情况,将shard尽量均匀分布到机器的各个磁盘;

5.       优化节点间的任务分布,将任务尽量均匀地发布到各节点,避免单点阻塞问题;

6.       优化Lucene层建立索引的过程,目的是降低CPU占用率及IO,例如,禁用_all字段。

1.2 索引刷新间隔

默认情况下索引的refresh_interval1秒,这意味着数据写1秒后就可以被搜索到,每次索引的refresh会产生一个新的lucene段,这会导致频繁的segment merge行为,如果你不需要这么高的搜索实时性,应该降低索引refresh周期,如:

index.refresh_interval: 120s

1.3 Translog刷新间隔

默认设置下,translog的持久化策略为:每个请求都flush。对应配置项为:

index.translog.durability: request

这是影响Elasticsearch写入速度的最大因素。但是只有这样,写操作才有可能是可靠的,如果系统可以接受一定几率的数据丢失,调整translog持久化策略为周期性和一定大小的时候flush

index.translog.durability: async
index.translog.sync_interval: 120s
index.translog.flush_threshold_size: 3gb
index.translog.flush_threshold_period: 120m

1.4 段合并优化

segment merge操作对系统CPUIO占用都比较高,从es 2.0开始,merge行为不再由es控制,而是转由lucene控制。有以下调整开关:

index.merge.scheduler.max_thread_count:最大线程数
index.merge.policy.*

最大线程数的默认值为:

Math.max(1, Math.min(4, Runtime.getRuntime().availableProcessors() / 2))

是一个比较理想的值,如果你只有一块硬盘并且非SSD,应该把他设置为1,因为在旋转存储介质上并发写,由于寻址的原因,不会提升,只会降低写入速度。

index.merge.policy.floor_segment

该属性用于阻止segment的频繁flush,小于此值将考虑优先合并,默认为2M,可考虑适当降低此值,如1M

index.merge.policy.segments_per_tier

该属性指定了每层分段的数量,取值越小最终segment越少,因此需要merge的操作更多,可以考虑适当增加此值。默认为10,他应该大于等于

index.merge.policy.max_merge_at_once

"merge":{
"scheduler":{
"max_thread_count" : "1"
},
"policy":{
"segments_per_tier" : "20",
"max_merge_at_once": "20"
"floor_segment" : "1m",
"max_merged_segment" : "5g"
}
}

1.5 Indexing Buffer

indexing buffer在为doc建立索引时使用,当缓冲满时会刷入磁盘,生成一个新的 segment,这是除refresh_interval外另外一个刷新索引,生成新segment的机会。每个 shard有自己的indexing buffer,下面的关于这个buffer大小的配置需要除以这个节点上所有的shard数量。

indices.memory.index_buffer_size

默认为整个堆的10%,如30GB堆内存,约占300M,在大量的索引操作时,可以考虑适当增大,但不要超过20%

1.6 Bulk请求

1.       使用批量请求,设置合理的数据条数:使用bulk命令进行批量索引数据时,每批次提交的数据大小为5~15MB;比如每条数据大小为1k,那么建议批量提交的数据条数为5000条;当前集群的最佳批量请求大小,可以从5MB开始测试,缓慢增加这个大小,直到写入性能不能提升为止。

2.       每个批量请求中只处理一个索引的数据:一个bulk请求只写入一个索引的数据,不建议一个bulk请求同时写入多个索引的数据,不同索引的数据分多个bulk请求提交。

3.       建立索引的过程偏计算密集型任务,应该使用固定大小的线程池配置,来不及处理的放入队列,线程数量配置为CPU核心数+1,避免过多的上下文切换。队列大小可以适当增加,但一定要严格控制大小,过大的队列导致较高的GC压力,并可能导致FGC频繁发生。

1.7 磁盘间的任务均衡

如果你的部署方案是为path.data配置多个路径来使用多块磁盘, es在分配shard 时,落到各磁盘上的shard可能并不均匀,这种不均匀可能会导致某些磁盘繁忙,利用率达到100%,这种不均匀达到一定程度可能会对写入性能产生负面影响。

所以建议每个数据实例挂载单块磁盘。

1.8 节点间的任务均衡

为了在节点间任务尽量均衡,数据写入客户端应该把bulk请求轮询发送到各个节点。

当使用java api ,或者rest apibulk接口发送数据时,客户端将会轮询的发送的集群节点,节点列表取决于:

client.transport.snifftrue(默认为 false),列表为所有数据节点。

否则,列表为初始化客户端对象时添加进去的节点。

java apiTransportClientrest apiRestClient都是线程安全的,当写入程序自己创建线程池控制并发,应该使用同一个Client对象。在此建议使用rest api,兼容性好,只有吞吐量非常大才值得考虑序列化的开销,显然搜索并不是高吞吐量的业务。

观察bulk请求在不同节点上的处理情况,通过cat接口观察bulk线程池和队列情况,是否存在不均:

_cat/thread_pool/bulk?v

另外,也可以搭建NGINX服务来达到负载均衡。

1.9 分片均匀分布

配置total_shards_per_node参数,让分片更加均匀的分布在各个实例上。表示限制每个实例上分布该该索引的分片最大个数,如2,即表示每个实例上最多分布2个该索引的分片。

说明:total_shards_per_node参数值=索引总分片数/数据实例数(向上取整)。

1.10 索引过程调整和优化

1.10.1 自动生成doc ID

分析es写入流程可以看到,写入doc时如果是外部指定了ides会先尝试读取原来doc的版本号,判断是否需要更新,使用自动生成doc id可以避免这个环节,从而避免出现在磁盘IOPS能力不足的情况下,磁盘IO被读IO大量占用,导致写入速度受限于磁盘IO

1.10.2 调整字段 Mappings

1.       字段的index属性设置为: not_analyzed,或者no。对字段不分词,或者不索引,可以节省很多运算,降低CPU占用。尤其是binary类型,默认情况下占用CPU非常高,而这种类型根本不需要进行分词做索引。

2.       调整_source字段:_source字段用于存储doc原始数据,对于部分不需要存储的字段,可以通过includes excludes来过滤,或者将_source 禁用,一般用于索引和数据分离。

3.       禁用_all字段:_all字段默认是开启的,其中包含所有字段分词后的关键词,作用是可以在搜索的时候不指定特定字段,从所有字段中检索。如果你不需要这个特性,可以禁用_all,可以小幅的降低CPU 压力,对速度影响并不明显。


相关文章

MySQL运维实战之Clone插件(10.2)Clone插件原理

MySQL运维实战之Clone插件(10.2)Clone插件原理

clone插件实现clone操作主要分为几个阶段:1、初始阶段。初始阶段,会开启页面跟踪(Page Tracking)。开启页面跟踪后,修改过的页面的编号会被记录下来。页面的修改可分为两个阶段:首先在...

寻找CPU使用率高进程方法

寻找CPU使用率高进程方法

背景节点报CPU使用率高,需要定位是什么进程占用CPU使用率高。CPU使用率持续较高在对应节点使用 “top”命令,然后键盘输入“P”,即按照CPU使用率排序进程。执行ps -ef | grep &l...

K8S中 CNI 插件的解读

K8S中 CNI 插件的解读

一.CNI是什么首先我们介绍一下什么是 CNI,它的全称是 Container Network Interface,即容器网络的 API 接口。它是 K8s 中标准的一个调用网络实现的接口。Kubel...

SpringBootWeb 篇-深入了解 SpringBoot + Vue 的前后端分离项目部署上线与 Nginx 配置文件结构(2)

SpringBootWeb 篇-深入了解 SpringBoot + Vue 的前后端分离项目部署上线与 Nginx 配置文件结构(2)

        3.0 在云服务器进行环境配置        将项目放到云服务器上运行,那么离不开项目所依赖的环境,比如...

mysql高可用配置(一)

一、简介MySQL使用双向半同步复制模式,通过开源的keepalived实现自动切换,应用通过vip连接数据库。配合自定义脚本,实现故障安全切换,切换过程对应用透明。二、部署主从2.1、在主备节点部署...

pod内无法访问slb的监听

pod内无法访问slb的监听

问题背景在A账号下的k8s集群中有个nginx 应用,需要去访问B账号下内网slb代理的一个服务。B账号下的slb有多条监听,测试发现只有个别监听可以telnet通,其余监听telnet均不通。可能是...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。