背景:数据进入到Elasticsearch当中之后,如何才能让数据被更快的检索使用,用一句话概括就是“开新文件”,但是每一秒都在打开新文件,一天有86400秒,设想一下,每次请求都要扫描86400个文件,这个性能肯定好不了。
归并线程
segment归并的过程,需要先读取segment,归并计算,再写一遍segment,最后刷到磁盘。这是一个非常消耗磁盘和IO的任务,所以我们需要对归并线程进行限速,默认配置是20MB,这对于写入量大,磁盘转速高,这个配置明显是过低的,所以我们需要提高限速。
# curl -XPuT http://127.0.0.1:9200/cluster/settings -d'
"persistent":{
"indices.store.throttle.maxbytes per sec":"100mb"
归并策略
归并线程是按照一定的运行策略来挑选segment 进行归并的主要为以下几条:
- index.merge.policy.floor_segment 默认 2MB,小于这个大小的 segment,优先被归并
- index.merge.policy.max merge at once 默认一次最多归并10个segment。
- index.merge.policy.max merge _at once_explicit 默认 forcemerge 时一次最多归并 30个segment.
- index.merge.policy.max_merged segment默认5 GB,大于这个大小的segment,不用参与归并。optimize 除外。
shard的allocate控制
以下几种情况会触发分配动作:
- 新索引生成
- 索引的删除。
- 新增副本分片
- 节点增减引发的数据均衡。
Elasticsearch 提供了一系列参数详细控制这部分逻辑:
- cluster.routing.allocation.enable 参数用来控制允许分配哪种分片。默认是 all。可选项还包括 primaries和new_primaries。none 则彻底拒绝分片。
- cluster.routing.allocation.allow rebalance 参数用来控制什么时候允许数据均衡。默认是indicesall active,即要求所有分片都正常启动成功以后,才可以进行数据均衡操作,否则的话,在集群重启阶段,会浪费太多流量了。
- cluster.routing.allocation.cluster concurrent rebalance参数用来控制集群内同时运行的数据均衡任务个数。默认是2个。如果有节点增减,且集群负载压力不高的时候可以适当加大。
- cluster.routing.allocation.node initial primaries recoveries参数用来控制节点重启时允许同时恢复几个主分片。默认是4个。如果节点是多磁盘,且I0压力不大,可以适当加大。
- cluster.routing.allocation.node concurrent recoveries参数用来控制节点除了主分片重启恢复以外其他情况下,允许同时运行的数据恢复任务。默认是2个。所以,节点重启时可以看到主分片迅速恢复完成,副本分片的恢复却很慢。除了副本分片本身数据要通过网络复制以外,并发线程本身也减少了一半。当然,主分片一定是本地恢复,副本分片却需要走网络,带宽是有限的。
- indices.recovery.concurrent streams参数用来控制节点从网络复制恢复副本分片时的数据流个数。默认是3个。
- indices.recovery.max_bytes_per _sec参数用来控制节点恢复时的速率。默认是 40MB。也可根据上面配置加大
分片分配控制策略
磁盘限额--为了保护节点数据安全,Elasticsearch会定时(cluster.info.update.interval,默认 30秒)检查一下各节点的数据目录磁盘使用情况。
在达到clusterrouting.allocation.disk.watermark.low(默认85%)的时候,新索引分片就不会再分配到这个节点上了。在达到 cluster.routing.allocation.disk.watermark.high(默认 90%)的时候,就会触发该节点现存分片的数据均衡,把数据挪到其他节点上去。这两个值不但可以写百分比,还可以写具体的字节数。出于成本考虑,对磁盘使用率有一定的要求,需要适当抬高这个配置:
# curl-XPuT localhost:9200/cluster/settings -d'{"transient":{
"cluster,routing.allocation.disk.watermark.low""85%"
"cluster.routing.allocation.disk.watermark.high":"10qb"
"cluster.info.update.interval":"1m"
热索引分片不均--默认情况下,Elasticsearch集群的数据均衡策略是以各节点的分片总数(indicesall active)作为基准的。这对于搜索服务来说无疑是均衡搜索压力提高性能的好办法。但是对于ELKstack场景,一般压力集中在新索引的数据写入方面。正常运行的时候,也没有问题。但是当集群扩容时,新加入集群的节点,分片总数远远低于其他节点。这时候如果有新索引创建,Elasticsearch的默认策略会导致新索引的所有主分片几乎全分配在这台新节点上。整个集群的写人压力,压在一个节点上,结果很可能是这个节点直接被压死,集群出现异常。所以,对于ELKstack场景,建议预先计算好索引的分片数后,配置好单节点分片的限额。比如,一个5节点的集群,索引主分片10个,副本1份。则平均下来每个节点应该有4个分片,那么就配置:
#curl-s-XPuT http://127.0.0.1:9200/logstash-2015.05.08/ settings -d '{"index":{"routing.allocation.total shards per node" :"5"
注意,这里配置的是5而不是4。因为我们需要预防有机器故障,分片发生迁移的情况如果写的是4,那么分片迁移会失败。
- cluster.routing.allocation.balance.shard 节点上分配分片的权重,默认值为 0.45。数值越大越倾向于在节点层面均衡分片。
- cluster.routing.allocation.balance.index每个索引往单个节点上分配分片的权重,默认值为0.55。数值越大越倾向于在索引层面均衡分片。
- cluster.routing.allocation.balance.threshold 大于阈值则触发均衡操作。默认值为1。