非常哇塞的 ES读场景、写场景 性能优化指南!你值得拥有!

标签: dev | 发表时间:2022-01-03 00:00 | 作者:
出处:http://itindex.net/relian

原创:小姐姐味道(微信公众号ID:xjjdog),欢迎分享,转载请保留出处。

ES作为NoSQL数据库里非常重要的一员,使用越来越广泛。虽然它因为索引延迟的原因,数据在时效性上有一些缺陷,但其大容量、分布式的优秀设计,使得它在时效性要求并不是特别高的类实时搜索领域,能够大展身手。

根据使用场景和用途,ES可以分为写入和读取两种典型的应用方式。比如ELKB,我们就需要额外关注它的 写优化;再比如从MySQL中同步数据到ES的宽表,我们就需要额外关注它的 读优化

废话不多说,我们直接show一下优化方法。如果你对ES的一些概念还不是很清楚,建议收藏本文慢慢看。

1.写入优化

日志属于写多读少的业务场景,对写入速度要求很高。拿我们其中一个集群来说,单集群日志量达到百TB,每秒钟日志写入量达到10W条。

数据写入,主要有三个动作:flush、refresh和merge。通过调整它们的行为,即可在性能和数据可靠性之间进行权衡。

1.1 translog异步化

首先,ES需要写一份translog,它类似于MySQL中的redolog,为的是避免在断电的时候数据丢失。ES默认每次请求都进行一次flush,但对于日志来说,这没有必要,可以将这个过程改为异步的,刷盘间隔为60秒。参数如下:

  curl-H"Content-Type: application/json"-XPUT'http://localhost:9200/_all/_settings?preserve_existing=true'-d'{   
  "index.translog.durability" : "async",
  "index.translog.flush_threshold_size" : "512mb",
  "index.translog.sync_interval" : "60s"
}'

这可以说是最重要的一步优化了,对性能的影响最大,但在极端情况下会有丢失部分数据的可能。对于日志系统来说,是可以忍受的。

1.2 增加refresh间隔

除了写translog,ES还会将数据写入到一个缓冲区中。但是注意了!此时,缓冲区的内容是无法被搜索到的,它还需要写入到segment里面才可以,也就是刷新到lucence索引里面。这就是refresh动作,默认1秒。也就是你写入的数据,大概率1秒之后才会被搜索到。

这也是为什么ES不是实时搜索系统的原因,它从数据写入到数据读出,一般是有一个合并过程的,有一定的时间差。

通过index.refresh_interval可以修改这个刷新间隔。

对于日志系统来说,当然要把它调大一点啦。xjjdog这里调整到了120s,减少了这些落到segment的频率,I/O的压力自然会小,写入速度自然会快。

  curl-H"Content-Type: application/json"-XPUT'http://localhost:9200/_all/_settings?preserve_existing=true'-d'{   
  "index.refresh_interval" : "120s"
}'

1.3 merge

merge其实是lucene的机制,它主要是合并小的segment块,生成更大的segment,来提高检索的速度。

原因就是refresh过程会生成一大堆小segment文件,数据删除也会产生空间碎片。所以merge,通俗来讲就像是碎片整理进程。像postgresql等,也有vaccum进程在干同样的事。

显而易见,这种整理操作,既浪费I/O,又浪费CPU。

如果你的系统merge非常频繁,那么调整merge的块大小和频率,是一个比较好的方法。

2.读取优化

2.1 指定路由

如果你向ES里写数据,那么它会为你设置一个离散的隐藏ID,落到哪个分片,是不一定的。如果你根据一个查询条件查询数据,你设置了6个shards的话,它要查询6次才行。如果能够在路由的时候就知道数据在哪个分片上,查询速度自然会上升,这就要求我们在构造数据的时候,人工指定路由规则。它的实际运行规则如下:

  shard = hash(routing) % number_of_primary_shards   

比如,一个查询会变成这样。

  GET my-index-000001/_search   
{
  "query": {
    "terms": {
      "_routing": [ "user1" ] 
    }
  }
}

当然,如果你的查询维度较多,又对数据的查询速度有非常高的有求,根据routing存放多份数据是一个比较好的选择。

2.2 rollover冷热分离

rollover根据索引大小,文档数或使用期限自动过渡到新索引。当rollover触发后,将创建新索引,写别名将更新为指向新索引,所有后续更新都将写入新索引,比如 indexname-000001.这种模式。

从rollover这个名字可以看出来,它和Java的log日志有一定的相似之处,比如Log4j的RollingFileAppender。

当索引变的非常大,通常是几十GB,那它的查询效率将变的非常的低,索引重建的成本也较大。实际上,很多索引的数据在时间维度上有较为明显的规律,一些冷数据将很少被用到。这个时候,建立滚动索引将是一个比较好的办法。

滚动索引一般可以与索引模板结合使用,实现按一定条件自动创建索引,ES的官方文档有具体的_rollover建立方法。

2.3 使用BoolQuery替代TermQuery

Bool查询现在包括四种子句,must、filter、should和must_not。Bool查询是true、false对比,而TermQuery是精确的字符串比对,所以如果需求相似,BoolQuery自然会快于TermQuery。

2.4 将大查询拆成分段查询

有些业务的查询比较复杂,我们不得不拼接一张非常大的宽表放在ES中,这有两个比较明显的问题。

  1. 宽表的数据往往需要从其他数据源中回查拼接而成,数据更新时对源库或者ES本身都有较大的压力
  2. 业务的查询JSON需要书写的非常复杂,查询效率未知,一次查询锁定的内存过高,无法进行深入优化

其实,宽表不论在RDBMS中还是ES中,都会与复杂的查询语句有关,其锁定时间都较长,业务也不够灵活。

应对这种场景的策略,通常将复杂的数据查询,转移到业务代码的拼接上来。比如,将一段非常冗长的单条查询,拆分成循环遍历的100条小查询。所有的数据库都对较小的查询请求有较好的响应,其整体性能整体上将优于复杂的单条查询。

这对我们的ES索引建模能力和编码能力提出了挑战。毕竟,在ES层面,互不相关的几个索引,将作为整体为其他服务提供所谓的数据中台接口。

2.5 增加第一次索引的速度

很多业务的索引数据往往来自于MySQL等传统数据库,第一次索引往往是全量索引,后面才是增量索引。必要的时候,也会进行索引的重建,大量的数据灌入造成了ES的索引速度建立缓慢。

为了缓解这种情况,建议在创建索引的时候,把副本数量设置成1,即没有从副本。等所有数据索引完毕,再将副本数量增加到正常水平。

这样,数据能够快速索引,副本会在后台慢慢复制。

3.通用优化

当然,我们还可以针对ES做一些通用的优化。比如,使用监控接口或者trace工具,发现线程池有明显的瓶颈,则需要调整线程池的大小。

具体的优化项如下。

3.1 线程池优化

新版本对线程池的配置进行了优化,不需要配置复杂的search、bulk、index线程池。有需要配置下面几个就行了:thread_pool.get.size, thread_pool.write.size, thread_pool.listener.size, thread_pool.analyze.size。具体可观测_cat/thread_pool接口暴露的数据进行调整。

3.2 物理冷热分离

上面的rollover接口,我们可以实现索引滚动。但是如何将冷数据存放在比较慢但是便宜的节点上?如何将某些索引移动过去?

ES支持给节点打标签,具体方式是在elasticsearch.yml文件中增加一些属性。比如:

  //热节点   
node.attr.temperature: hot 
//冷节点
node.attr.temperature: cold 

节点有了冷热属性后,接下来就是指定数据的冷热属性,来设置和调整数据分布。ES提供了index shard filtering功能来实现索引的迁移。

首先,可以对索引也设置冷热属性。

  PUT hot_data_index/_settings   
{
    "index.routing.allocation.require.temperature": "hot"
}

这些索引将自动转移到冷设备上。我们可以写一些定时任务,通过_cat接口的数据,自动的完成这个转移过程。

3.2 多磁盘分散I/O

其实,可以通过配置多块磁盘的方式,来分散I/O的压力,但容易会造成数据热点集中在单块磁盘上。

ES支持在一台机器上配置多块磁盘,所以在存储规模上有更大的伸缩性。在配置文件中,配置path.data属性,即可挂载多块磁盘。

  path.data : /data1, /data2, /data3   

值得注意的是,如果你是在扩容,那么就需要配合reroute接口进行索引的重新分配。

3.3 减少单条记录的大小

Lucene的索引建立过程,非常耗费CPU,可以减少倒排索引的数量来减少CPU的损耗。第一个优化就是减少字段的数量;第二个优化就是减少索引字段的数量。具体的操作,是将不需要搜索的字段,index属性设置为not_analyzed或者no。至于_source和_all,在实际调试中效果不大,不再赘述。

End

ES的使用越来越广泛,从ELKB到APM,从NoSQL到搜索引擎,ES在企业中的地位也越来越重要。本文通过分析ES写入和读取场景的优化,力求从原理到实践层面,助你为ES加速。希望你在使用ES时能够更加得心应手。

通常,一个ES集群对配置的要求是较高的,尤其是APM等场景,甚至会占到PaaS平台的1/3资源甚至更多。ES提供了较多的配置选项,我们可以根据应用场景,调整ES的表现,使其更好的为我们服务。

作者简介: 小姐姐味道 (xjjdog),一个不允许程序员走弯路的公众号。聚焦基础架构和Linux。十年架构,日百亿流量,与你探讨高并发世界,给你不一样的味道。我的个人微信xjjdog0,欢迎添加好友,进一步交流。

相关 [es 性能优化 值得] 推荐:

ES性能优化总结

- - 互联网 - ITeye博客
    Elasticsearch是目前大数据领域最热门的技术栈之一,经过近8年的发展,已从0.0.X版升级至6.X版本,虽然增加了很多的特性和功能,但是在主体架构上,还是没有太多的变化. 下面就把我对于ES使用实践的一些经验总结一下,供大家参考;也请大家拍砖. 如果有条件,尽可能使用SSD硬盘, 不错的CPU.

非常哇塞的 ES读场景、写场景 性能优化指南!你值得拥有!

- - IT瘾-dev
原创:小姐姐味道(微信公众号ID:xjjdog),欢迎分享,转载请保留出处. ES作为NoSQL数据库里非常重要的一员,使用越来越广泛. 虽然它因为索引延迟的原因,数据在时效性上有一些缺陷,但其大容量、分布式的优秀设计,使得它在时效性要求并不是特别高的类实时搜索领域,能够大展身手. 根据使用场景和用途,ES可以分为写入和读取两种典型的应用方式.

ES优化总结

- - 非技术 - ITeye博客
最近一直在研究ES集群,也看了很多篇前辈们总结的博客,同事借鉴了官方给出的一些建议,做了一下几点总结,希望对后来者有用:. 为了防止ES进程的内存被置换到磁盘上(会导致在检索的时候发生内存交换导致检索速度迟缓)引起性能急速下降. 候可以把config/elasticsearch.yml中的bootstrap.mlockall设置为true就可以了.

es的连接查询

- - 行业应用 - ITeye博客
在一般的关系型数据库中,都支持连接操作. 在ES这种分布式方案中进行连接操作,代价是十分昂贵的. 不过ES也提供了相类似的操作,支持水平任意扩展,实现连接的效果. 其他内容, 参考Elasticsearch官方指南整理. 在ES中支持两种连接方式:嵌套查询 和 has_child、has_parent父子查询.

ElasticSearch —修改ES数据

- -
ElasticSearch能够以接近实时的速度提供数据操作和搜索功能. 在默认情况下,从索引/更新/删除数据到出现在搜索结果之间,你可能会感受到有1秒的延迟时间(刷新间隔). 这是与SQL等其他平台的一个重要区别,这些平台在完成事务之后,它们的数据立即可用. 先前,我们已经知道如何索引一个单个的文档.

MySQL性能优化

- sun - IT程序员面试网
在笔试面试中,尤其是像百度,淘宝这些数据量非常大,而且用LAMP架构的公司,数据库优化方面就显得特别重要了. 此外,除了数据库索引之外,在LAMP结果如此流行的今天,数据库(尤其是MySQL)性能优化也是海量数据处理的一个热点. 下面就结合自己的经验,聊一聊MySQL数据库优化的几个方面. 首先,在数据库设计的时候,要能够充分的利用索引带来的性能提升,至于如何建立索引,建立什么样的索引,在哪些字段上建立索引,上面已经讲的很清楚了,这里不在赘述.

Hebernate 性能优化

- - 企业架构 - ITeye博客
文章分为十三个小块儿对Hibernate性能优化技巧进行总结性分析,分析如下:. 一、在处理大数据量时,会有大量的数据缓冲保存在Session的一级缓存中,这缓存大太时会严重显示性能,所以在使用Hibernate处理大数 据量的,可以使用session. clear()或者session. evict(Object) 在处理过程中,清除全部的缓存或者清除某个对象.

Hbase 性能优化

- - CSDN博客云计算推荐文章
因 官方Book Performance Tuning部分章节没有按配置项进行索引,不能达到快速查阅的效果. 所以我以配置项驱动,重新整理了原文,并补充一些自己的理解,如有错误,欢迎指正. 默认值:3分钟(180000ms). 说明:RegionServer与Zookeeper间的连接超时时间.

JavaScript性能优化

- - ITeye博客
互联网泡沫让投资者长了记性:态度更加谨慎.         如今主流浏览器都在比拼JavaScript引擎的执行速度,但最终都会达到一个理论极限,即无限接近编译后程序执行速度. 这种情况下决定程序速度的另一个重要因素就是代码本身. 在这里我们会分门别类的介绍JavaScript性能优化的技巧,并提供相应的测试用例,供大家在自己使用的浏览器上验证, 同时会对特定的JavaScript背景知识做一定的介绍.

Mysql性能优化

- - 数据库 - ITeye博客
MySQL性能优化.   性能优化是通过某些有效的方法来提高MySQL的运行速度,减少占用的磁盘空间. 性能优化包含很多方面,例如优化查询速度,优化更新速度和优化MySQL服务器等.   数据库管理人员可以使用SHOW STATUS语句来查询MySQL数据库的性能. 语法:SHOW STATUE LIKE ‘value’;其中value参数是常用的几个统计参数.