ElasticSearch性能调优

写优化

对于写索引负载很高但是对检索性能不是很高的场景,采用优秀的写索引策略就非常重要了,可以尝试一下几个方面在提升写索引的性能

  1. 批量提交
    当有大量的写任务时,使用批量提交是一种比较好的方案,每次提交的最优数据量受数据类型、网络情况、集群状态等因数的影响,通常策略如下
    (1)批量提交的数据条数一般是根据文档的大小和服务器性能而定的,但是一次批处理的数据大小应从5M~15M开始,逐渐增加,直到性能没有提升时才结束。
    (2)在通过增加一次提交的数据量大小没有显著的提升效果时,可以考虑逐渐增加并发写入数
    (3)若抛出EsRejectedExecutionException错误,则表明集群已经没有处理能力了,说明至少有一种资源已经到达瓶颈,这时需要升级到达瓶颈的资源或者增加节点
  2. 合理使用段合并
    ElasticSearch底层是使用的Lucene,而Lucene是以段的形式存储数据的,每当有新的数据写入索引时,就会自动创建一个新的段,所以在一个索引文件中包含多个段,随着数据量的不断增加,段的数量也会不断增加,需要消耗的文件句柄和CPU也会逐渐增加,查询性能就会受到影响,Lucene后台定期会进行段的合并,但是段合并计算量庞大,会消耗大量的I/O,ElasticSearch默认策略为
    (1)当段合并的速度落后于索引的写入速度时,为了避免堆积段,ElasticSearch会把写索引的线程数量减少到1,并打印"now throttling indexing"这样的信息
    (2)为了防止因段合并影响检索性能,ElasticSearch默认对段合并的速度进行限制,默认是20m/s。但是,如果使用的是SSD,就可以通过下面的命令将这个限制增加到100m/s
PUT /_cluster/settings
{
"persistent":{
"indices.store.throttle.max_bytes_per_sec":"100mb"
}
}
  1. 减少refresh次数
    ElasticSearch在写索引时采用延迟写入的策略来提升写入性能,默认为1秒会触发一次refresh,refresh会把内存中的数据以段的形式刷新到文件缓存系统中,对于搜索延时要求不高的场景,可以适当提高触发refresh的时间,比如30秒,这样还可以减少段的数量,降低段合并的压力,但是需要消耗更多的内存资源,可以通过以下参数来配置
index.refresh_interval:30s
  1. 减少flush次数
    当事务日志(Translog)的数据量达到512M或者30分钟时,会触发一次Flush,将文件缓存系统中的数据持久化到硬盘,Flush是一个比较耗时的操作,可以适当增加数据量的大小来减少Flush的频率,当然这样意味着文件缓存需要存储更多的数据,也就是需要消耗更多的内存,比如增加到1G,配置如下
index.translog.flush_threshold_size:1024mb
  1. 减少副本数量
    ElasticSearch的副本虽然可以提高集群的可用性,同时可以提高检索的并发数,却会严重影响写入的性能,在写索引时需要把整个文档的内容都发送给副本节点,而所有的副本节点都需要执行一次写索引过程,所以在设置副本数量时,可以适当少一点,一般设置为3即可

读优化

  1. 避免大结果集合深翻
    查询条件携带from和size时,查询结果集将会包含n * (from + size)条数据, n为分片数,如果from、size、n中任意一个值很大,则参与排序的数据量就会越大,消耗的cpu、内存以及带宽就会越多,为了解决这种问题,ElasticSearch提供scroll和scroll-scan这两种查询方式
    (1)scroll:是为了检索大量的结果(甚至所有的数据)而设计的,假如进行一次批量请求,要查询1~100页的数据,每页有100条数据,如果使用普通查询,则每次在每个分片查询得分(score)最高的from+size条数据,然后协调节点将 所有分片返回的结果汇总在进行排序,然后返回from+1开始的size条数据,每一页都需要经过这样一次查询,而scroll将查询每个分片上得分最高的10000条数据,然后协调节点将所有结果进行汇总排序,将排名前10000的数据进行快照,每次换页只需要将数据开始值进行调整即可,减少了查询和排序的次数,但在第一次查询时会慢很多
    (2)scroll-scan:scroll使用快照保存了要返回的结果,减少了查询和排序的次数,但是在初次查询比较耗时,scroll-scan是一种更高效的大数量查询方案,和scroll基本一致,但是scroll-scan关闭了scroll最耗时的文本相似度计算和排序,使其性能更加高效
    虽然scroll-scan更高效,但是ElasticSearch在2.10版本中被废弃了,ElasticSearch 5以后的版本将会移除
  2. 选择合适的路由
    在多分片的ElasticSearch集群中,对于检索大致分为以下两种
    (1)在查询条件中包含routing信息。即查询可以根据routing信息直接定位到其中的一个分片进行查询,而不需要查询所有的分片
    (2)如果查询条件中不包含routing信息,在查询时就不知道数据具体在哪个分片上,所以需要查询所有的分片,查询过程分为Scatter、Gather两个阶段
    Scatter:在请求到达协调节点后,协调节点吧查询请求分发到每个分片上。
    Gather:协调节点搜素在每个分片上完成的结果集,再讲结果集进行重新排序,然后返回数据给客户端
    使用routing查询时性能要比不使用routing好很多,在查询时尽量使用routing来提升检索性能
  3. SearchType
    SearchType有以下四种方式,可以根据实际场景选择一种最优的方式
    (1)QUERY_THEN_FETCH:ElasticSearch默认使用方式,分两步完成,第一步先向所有分片发出请求,各分片只返回文档的相似度得分(score)和id,而不需要文档的详细信息,然后协调节点按照各分片返回的分数进行重新排序和排名,在筛选出返回给客户单的size个文档id;第二步使用第一步筛选出的id在相关分片取出文档的详细信息并返回给用户,虽然需要进行二次查询,但是在数据量结果集很大返回数量很小的情况可以节省大量的带宽
    (2)QUERY_AND_FETCH:协调节点向所有分片发出查询请求,各分片返回文档的详细信息以及相似度得分(score)和id,然后协调节点按照得分进行重新排序,在取出size个文档返回给客户端,只需要一次查询,所以性能是最好的
    (3)DFS_QUERY_THEN_FETCH:与QUERY_THEN_FETCH类似,它额外多一个阶段,在初始化查询中执行全局的词频计算,以使得更精确的打分,从而让查询结果更精确,性能比QUERY_THEN_FETCH更低
    (4)DFS_QUERY_AND_FETCH:与QUERY_AND_FETCH类似,只是使用的是全局词频
  4. 定期删除
    ElasticSearch删除一个文档后不会立即从硬盘中删除该文档,而是产生一个.del文件专门记录被删除的文档。而在检索过程中,被删除的文件还会参与检索,只不过最后会被过滤,如果删除的文件太多,这样也会影响查询性能,可以执行如下命令来定期删除这些文件
curl -XPOST http://hostname:port/_optimize?only_expunge_deletes=true 

JVM堆大小设置

ElasticSearch默认堆内存大小为1GB,由于ElasticSearch是一个比较耗内存的应用,对于大部分应用来说,这个值都显得太小,可以根据实际应用场景增加堆内存大小,比如设置为5GB,当然ElasticSearch堆内存的分配要考虑如下因素
(1)最好不要超过物理内存的50%
(2)堆内存大小最好不要超过32GB

磁盘配置优化

对ElasticSearch集群来说,硬盘的性能是非常重要的,特别是对于有大量写请求的业务场景,因为硬盘一般是服务器上最慢的一块,对于磁盘的选择提供一下几点建议
(1)条件允许,强烈建议使用固态硬盘(Solid State Disk)。SSD相比于机械硬盘具有更高的读写性能和稳定性
(2)使用RAID0,RAID0可以提升磁盘写入的速度
(3)在ElasticSearch的服务器上挂载多块硬盘,这样可以在多块硬盘上同时进行读写操作
(4)不要使用类似于NFS(Network File System)的远程存储设备,因为这些设备的延迟对性能影响非常大

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值