当前位置: 首页 > 后端技术 > Java

ES性能调优等特性

时间:2023-04-01 17:48:19 Java

一、编写优化批量提交。每次提交的数据量可以是最优的,受文件大小、数据类型、网络情况、集群状态等因素的影响。一般来说,一个batch的数据量应该从5M-15M逐渐增加,直到达到是没有性能的提花。优化存储设置。尽量使用固态硬盘(solidstatedisk)合理使用段合并。段合并的计算量巨大,消耗大量I/O。为了不让段合并影响搜索性能,我们需要控制一个合理的合并速度,可以参照配置减少刷新次数。这个需要根据实际情况来看。如果搜索的时效性不高,可以增加延迟刷新时间,这样也可以减少segmentmerge的次数。减少冲洗次数。这也需要结合实际情况。当translog数达到512M或30分钟时,将触发flush。磁盘持久化消耗更多资源。我们可以通过设置一个合理的参考值来减少副本数。ES的副本数可以保证集群的可用性,增加并发搜索数,但是会严重降低索引写入的效率,因为写入索引时需要将整个文档的内容发送到副本节点,并且所有副本节点都需要重复索引过程。所以份数不宜过多。其次,读取优化避免了大结果集和深度翻页。如果有N个分片,则协作节点需要从每个分片中收集最先的from+size条数据,然后将收集到的Nx(from+size)条数据合并并重新排序,最后从from+1size返回数据块。只要N、from、size其中一个值很大,这样的查询就会消耗大量CPU,效率低下。为了解决这类问题,ES提供了scroll和scroll-scan两种方式。1)滚动模式。与每次返回一页数据的搜索请求不同,scroll旨在检索大量结果(甚至所有结果)。比如我们有一个批量查询的需求,需要查询1到100页的数据。每页有100条数据,如果使用search查询,每次需要在每个分片上查询得分最高的from+size条数据,然后协作节点将收集到的n×(from+size)条数据并再次对其进行排序。然后从from+1返回size条数据,重复100次。随着from的增加,查询速度越来越慢。但是scroll的思路是:在每个shard上一次查询10000条数据,协同节点收集n×10000条数据,然后合并排序,将前10000条结果以快照的形式存储,并且最后以类似于数据的数据库游标部分的形式依次获取它们。这种方式的好处是减少了查询和排序的次数。scroll除了第一次查询返回查询结果外,还会返回一个scroll_id,这是下一次请求的参数。Scroll也分为两个阶段:query和fetch。第一阶段,查询先查询,暂存所有符合条件的doc_id;第二阶段fetch根据doc_id和scroll_id以游标形式获取文档。需要注意的是,scroll会以快照的形式临时存储数据。如果数据在后续一段时间内被修改,则不会被感知到,所以不适合实时性要求高的场景。2)滚动扫描法。scroll需要在初始查询时进行文本相似度计算和排序,同样比较耗时,scroll-scan关闭了这个过程。scroll-scan的特点是不进行文本相似度计算;不支持聚合选择合适的路由。在multi-shardES集群中,查询大致可以分为以下两种。1)查询条件包含路由信息。查询时,可以直接根据路由定位其中一个分片,而不是查询所有分片,然后通过协调节点进行二次排序。2)如果查询条件不包含路由,则整个查询过程分为两个过程:scatter和gather。Scatter(分发):请求到达协调节点后,协调节点将查询请求分发到各个分片上Gather(聚合):协调节点收集在各个分片上完成的搜索结果,然后将收集到的结果集重新排序,返回给用户。3.堆大小设置ES默认的堆内存大小为1GB,因为ES是一个比较耗内存的应用,我们可以稍微调大这个值。-Xms与-Xmx设置相同。内存分配还有两个原则:最好不要超过物理内存的50%。ES底层由lucene实现。由于lucene段的不变性,我们不需要考虑数据更改。这对缓存非常友好。操作系统可以将这些文件缓存在操作系统的文件系统缓存中,而不是堆内存中,如果超出物理内存太多,留给文件缓存系统的就不多了。堆内存最好不要超过32G。这是因为在64位操作系统中,指针本身会变大,浪费在指针本身上的空间也会更多。性能调优写到这里,我们来看看ES中的一些特性,比如主节点选举,如何避免脑裂。角色隔离由于默认的node.master和node.data都是true,所以我们经常让Master节点同时承担Data节点的角色。Elasticsearch集群中的Data节点负责数据的增删改查、聚合等操作,因此会消耗大量的CPU、内存和I/O,并可能影响到Master节点,从而影响整个集群。状态。在搭建集群的时候,尤其是比较大的集群,我们应该按照角色对Elasticsearch集群中的节点进行划分和隔离。我们通常会使用几台配置比较低的虚拟机来搭建一个专用的Master集群。在集群中进行角色隔离非常简单,只需要在节点的配置文件中添加如下配置信息即可。候选主节点:node.master=truenode.data=false数据节点:node.master=falsenode.data=true选举主节点的条件:1)只有是候选主节点(master:true)的节点才能成为主节点2)最小主节点数(min_master_nodes)的目的是防止脑裂。ES的选举是ZenDiscovery模块的职责,主要包括Ping(节点通过这个RPC相互发现)和Unicast(unicast模块包含一个主机列表来控制哪些节点需要ping)这两部分。选举过程大致如下:第一步:确认候选主节点数量是否符合标准第二步:根据nodeId字典对所有候选主节点进行排序。A(0号)节点,暂时认为它是主节点第三步:如果某个节点的得票数达到一定值(候选主节点数/2+1)并且节点自己选举自己,那么这个节点就是master。否则,重复直到满足上述条件。避免split-brain脑裂是因为网络原因,集群内选举多个master,最后一个集群分裂成多个集群。为了防止脑裂,我们需要在Master集群节点的配置文件中添加参数discovery.zen.minimum_master_nodes,表示需要参与主节点选举的候选主节点的数量(即默认值为1)。我们通常应该将该值设置为(master_eligible_nodes/2)+1,其中master_eligible_nodes是Master集群中的节点数。这样做不仅可以防止脑裂现象,还可以最大化集群的高可用,因为只要有不少于discovery.zen.minimum_master_nodes的候选节点存活下来,选举就可以顺利进行。参考文章:elasticsearchscrollquery的原理不太懂Elasticsearch的SearchScroll原理分析及性能稳定性优化