Elasticarch性能调优:段合并(Segmentmerge)

更新时间:2023-05-12 09:22:03 阅读: 评论:0

Elasticarch性能调优:段合并(Segmentmerge)Elasticarch索引(elasticarch index)由⼀个或者若⼲分⽚(shard)组成,分⽚(shard)通过副本(replica)来实现⾼可⽤。⼀个分⽚(share)其实就是⼀个Lucene索引(lucene index),⼀个Lucene索引(lucene index)⼜由⼀个或者若⼲段(gment)组成。所以,当我们查询⼀个Elasticarch索引时,查询会在所有分⽚上执⾏,既⽽到段(gment),然后合并所有结果。
此⽂将从gment的视⾓,分析如何对Elasticarch进⾏索引性能的优化。
倒排索引
Elasticarch可以对全⽂进⾏检索主要归功于,倒排索引被写⼊磁盘后是不可改变的,永远不能被修改。倒排索引的不变性有⼏个好处:
因为索引不能更新,不需要锁
⽂件系统缓存亲和性,由于索引不会改变,只要系统内存⾜够,⼤部分读请求直接命中内存,可以极⼤提⾼性能
其他缓存,如filter缓存,在索引的⽣命周期内始终有效
写⼊单个⼤的倒排索引允许数据被压缩,减少磁盘I/O和需要被缓存到内存的索引的使⽤量
但倒排索引的不变性,同样意味着当需要新增⽂档时,需要对整个索引进⾏重建,当数据更新频繁时,这个问题将会变成灾难。那Elasticarch索引近似实时性,是如何解决这个问题的呢?
段(gment)
Elasticarch是基于Lucene来⽣成索引的,Lucene引⼊了“按段搜索”的概念。⽤更多的倒排索引来反映最新的修改,这样就不需要重建整个倒排索引⽽实现索引的更新,查询时就轮询所有的倒排索引,然后对结果进⾏合并。
除了上⾯提到的”段(gment)”的概念,Lucene还增加了⼀个”提交点(commit point)”的概念,”提交点(commit point)”⽤于列出了所有已知的”段”。
索引更新过程(段的不断⽣成)
索引的更新过程可以通过refresh api和flush API来说明。
refresh API
从内存索引缓冲区把数据写⼊新段(gment)中,并打开,可供检索,但这部分数据仍在缓存中,未写⼊磁盘。默认间隔是1s,这个时间会影响段的⼤⼩,对段的合并策略有影响,后⾯会分析。可以进⾏⼿动刷新:
1 2 3 4 5# 刷新所有索引
POST /_refresh
# 指定刷新索引
POST /index_name/_refresh
flush API
执⾏⼀个提交并且截断translog的⾏为在Elasticarch被称作⼀次flush。每30分钟或者translog太⼤时会进⾏flush,所以可以通过translog的设置来调节flush的⾏为。完成⼀次flush会有以下过程:
所有在内存缓冲区的⽂档都被写⼊⼀个新的段。
缓冲区被清空。
⼀个提交点被写⼊硬盘。
⽂件系统缓存通过fsync被刷新(flush)。
⽼的translog被删除。
段合并(gment merge)
每次refresh都产⽣⼀个新段(gment),频繁的refresh会导致段数量的暴增。段数量过多会导致过多的消耗⽂件句柄、内存和CPU时间,影响查询速度。基于这个原因,Lucene会通过合并段来解决这个问题。
但是段的合并会消耗掉⼤量系统资源,尤其是磁盘I/O,所以在Elasticarch 6.0版本之前对段合并都有“限流(throttling)”功能,主要是为了防⽌“段爆炸”问题带来的负⾯影响,这种影响会拖累Elasticarch的写⼊速率。当出现”限流(throttling)”时,Elasticarch⽇志⾥会出现类似如下⽇志:
1 2now throttling indexing: numMergesInFlight=7, maxNumMerges=6 stop throttling indexing: numMergesInFlight=5, maxNumMerges=6
但有时我们更在意索引批量导⼊的速度,这时我们就不希望Elasticarch对段合并进⾏限流,可以通过indices.store.throttle.max_bytes_per_c提⾼限流阈值,默认是20MB/s:
1 2 3PUT /_cluster/ttings {
"persistent" : {
4 5 6        "indices.store.throttle.max_bytes_per_c" : "200mb"    }
}
当然也可以关掉段合并限流,”indices.pe”设置为none即可:
1 2 3 4 5 6PUT /_cluster/ttings
{
"transient" : {
"indices.pe" : "none"    }
}
需要注意的是,这⾥的”限流(throttling)”是对流量(注意单位是Byte)进⾏限流,⽽不是限制进程(scheduler.max_thread_count)。indices.pe和indices.store.throttle.max_bytes_per_c在版本6.x已被移除,在使⽤中经常会发现”限速(throttling)”是并发数(scheduler.max_thread_count),这两个参数感觉很鸡肋。
但即使上⾯的限流关掉(none),我们在Elasticarch⽇志⾥仍然能看到”throttling”⽇志,这主要是因为
**merge**的线程数达到了最⼤,这个最⼤值通过参数scheduler.max_thread_count来设置,这个配置不能动态更新,需要设置在配置⽂件l⾥:
这个设置允许 max_thread_count + 2 个线程同时进⾏磁盘操作,也就是设置为 3 允许5个线程。默认值是 Math.min(3,
段合并策略(Merge Policy)
这⾥讨论的Elasticarch版本是1.6.x(⽬前使⽤的版本,有点⽼),这个版本⾥⽤的搜索引擎版本是Lucene4,Lucene4中段的合并策略默认使⽤的是TieredMergePolicy,所以在Elasticarch 1.6中,旧的已经被弃⽤,在Elasticarch 2.x⾥这些参数直接就被移除了。所以这节主要是讨论跟TieredMergePolicy有关的调优(在版本6.x⾥,merge相关的参数都被移除)。
TieredMergePolicy的特点是找出⼤⼩接近且最优的段集。⾸先,这个策略会计算在当前索引中可分配的段(gment)数量预算(budget,代码中变量allowedSegCount,通过index总⼤⼩totIndexBytes和最⼩段⼤⼩minSegmentBytes进⾏⼀系列计算获得),如果超预算(budget)了,策略会对段(gment)安
装⼤⼩进⾏降序排序,找到*最⼩成本(least-cost)的段进⾏合并。最⼩成本(least-cost)*由合并的段的”倾斜度(skew,最⼤段除以最⼩段的值)”、总的合并段的⼤⼩和回收的删除⽂档的百分⽐(percent deletes reclaimed)来衡量。”倾斜度(skew)”越⼩、段(gment)总⼤⼩越⼩、可回收的删除⽂档越⼤,合并将会获得更⾼的分数。
这个策略涉及到⼏个重要的参数
max_merged_gment:默认5G,合并的段的总⼤⼩不能超过这个值。
floor_gment:当段的⼤⼩⼩于这个值,把段设置为这个值参与计算。默认值为2m。
max_merge_at_once:合并时⼀次允许的最⼤段数量,默认值是10。
gments_per_tier:每层允许的段数量⼤⼩,默认值是10。⼀般 >= max_merge_at_once。
当增⼤floor_gment或者fresh_interval的值时,minSegmentBytes(所有段中最⼩段的⼤⼩,最⼩值为floor_gment)也会变⼤,从⽽使allowedSegCount变⼩,最终导致合并频繁。当减⼩gments_per_tier的值时,意味着更频繁的合并和更少的段。floor_gment需要设置多⼤,这个跟具体业务有很⼤关系。
需要了解更多细节,可以阅读这篇⽂章:
再谈限流(throttling)
前⽂讲到Elasticarch在进⾏段合并时,如果合并并发线程超过scheduler.max_thread_count时,就会出现限流(throttling),这时也会拖累索引的速度。那如何避免throttling呢?
Elasticarch 1.6中,限速发⽣在,当TieredMergePolicy.findMerges策略返回的段数量超过了”maxNumMerges”值时,会激活限速。
”maxNumMerges”可以通过scheduler.max_merge_count来进⾏设置,默认设置为scheduler.max_thread_count + 2。这个参数在官⽅⽂档中找不到,不过可以动态更新:
1 2 3 4PUT /index_name/_ttings
{
"scheduler.max_merge_count": 100 }
不过这⾥有待进⼀步测试。
当然,也可以通过提⾼scheduler.max_thread_count参数来增加限流的阈值,尤其当使⽤SSD时:
在**段合并策略**⾥有提到,当增加fresh_interval的值时,⽣成⼤段(large gment)有可能使allowedSegCount变⼩,导致合并更频繁,这样出现并发限流的⼏率更⾼。可以通过增加anslog.flush_threshold_size(默认512 MB)的设置,提⾼每次清空触发(flush)时积累出更多的⼤段(larger gment)。刷新(flush)频率更低,⼤段(larger gment)合并的频率也就更低,对磁盘的影响更⼩,索引的速度更快,
但要求更⾼的heap内存。
原⽂:/2020/02/22/elasticarch-gment-merge/

本文发布于:2023-05-12 09:22:03,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/89/887312.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:合并   限流   需要   内存
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图