[转载] ElasticStack 系列之四 & 索引后半段过程

1. segment 归并的影响

影响原因:

由之前的讲解我们已经知道数据怎么进入 ElasticSearch 并且如何才能让数据更快的被检索使用。其中用一句话概括了 Lucene 的设计思路就是“开新文件”,但另一个方面看,开新文件也会给服务器带来负载压力。因为默认每 5s 都会有一个新文件产生,每个文件都需要有文件句柄、内存、CPU使用等各种资源,这样对应的响应性能绝对好不了!

ES解决办法:

为了解决这个办法,ElasticSearch 会不断在后台运行任务,主动将这些零散的 segment 做数据归并,尽量让索引内只保存少量的、每个比较大的 segment 文件。

这个过程是有独立的线程来进行的,并不影响新 segment 的产生。归并过程中,索引状态如上图所示,尚未完成的较大的 segment 是被排除在检索可见范围之外的,具体逻辑如下:

当归并完成,较大的这个 segment 刷到磁盘后,commit 文件作出相应的变更,删除之前几个小的 segment,改成新的大 segment。等检索请求都从小的 segment 转到大 segment 上以后,删除没用的小 segment。这时候,索引里 segment数量就下降了,具体状态图如下所示:

2-1. 归并线程的配置与策略

segment 归并的过程具体有:读取 segment–>归并计算–>再写一遍 segment–>刷到磁盘, 可以说这是一个非常消耗磁盘 I/O 和 CPU 的任务。所以,ElasticSearch 提供了对归并线程的限制机制,确保这个任务不会过分影响到其他任务。

默认情况下,归并线程的限速是:20MB/s , 对于写入量较大,磁盘转速较高,甚至使用 SSD 盘的服务器来说,这个限速明显过低,建议可以适当调大到 100MB 或者更高。

归并线程数目,ElasticSearch 也是有所控制的,默认归并线程的计算公式如下所示:

Math.min(3, Runtime.getRuntime().availableProcessors() / 2)

即服务器 CPU 核数的一半 > 3 时,启动 3 个归并线程;否则启动跟 CPU 核数的一半相等的线程数。一般的服务器 CPU 核数都会在6以上,所以一般来说归并线程数就是 3。如果你确定自己磁盘性能跟不上,可以降低 index.merge.scheduler.max_thread_count 配置,免得 I/O 情况恶化。

2-2. 归并策略

归并线程是按照一定的运行策略来挑选 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 默认 optimize 时一次最多归并 30 个。
  • index.merge.policy.max_merged_segment 默认 5GB,大于这个大小的 segment 不用参与归并,optimize 除外。

根据这段策略,我们可以从另一个角度考虑如何减少 segmen t归并的资源消耗以及提高高响应的办法:加大 flush 间隔,尽量让每次新生成的 segment 本身大小就比较大。

3. optimize

ElasticSearcch 默认最大的 segment 大小是 5GB。那么一个比较庞大的数据索引,就必然会有为数不少的 segment 永远存在,这对文件句柄、内存资源都是极大的浪费。但是由于归并任务太消耗资源,所以一般不太选择加大 index.merge.policy.max_merged_segment 配置,而是在负载较低的时间段,通过 optimize 接口,强制归并 segment。

curl -XPOST http://127.0.0.1:9200/logstash-2015-06.10/_optimize?max_num_segments=1

由于 optimize 线程对资源的消耗比普通的归并线程大得多, 所以, 绝对不建议对还在写入数据的热索引执行这个操作。

4. ES 数据写入流程

作为分布式系统,数据副本可算是一个标配。ElasticSearch 数据写入流程,自然也涉及副本。在有副本配置的情况下,数据从发向 ElasticSearch 节点–>到接到 ElasticSearch 节点响应返回流向如下图所示:

  1. 客户端请求发送给 Node1 节点,Node1 节点用数据的 _id 取余计算得到应该将数据存储到 shard0 上。通过 cluster state 信息发现 shard0 的主分片已经分配到了 Node3 上,Node1 转发请求数据给 Node3.

  2. Node3 完成请求数据的索引过程,存入主分片 P0 上。然后并行转发数据给分配有 shard0 的副本分片的 Node1 和 Node2。当Node1 和 Node2 节点同时汇报 coordinating 节点说 数据写入成功, 即会返回成功响应给客户端。

这个过程有几个参数可以用来控制或变更其行为:

  1. consistency:在上示例中,两个副本分片只要有一个成功就可以返回给客户端了。这点也是有配置的。ElasticSearch默认值的计算公式如下所示:

int((primary + number_of_replicas)/ 2)) + 1

  1. timeout:如果集群出现异常,有些分片当前不可用,ElasticSearch 默认会等待 1 分钟看分片能否恢复。可以使用 ?timeout=30s 参数来缩短这个等待时间。

副本配置和分片配置不一样,是可以随时调整的。有些较大的重建索引的应用场景,设置可以在 optimize 前,先把副本全部取消掉,等 optimize 或者重建索引之后,再重新开启副本,节约单个 segment 的重复归并消耗。

curl -XPUT http://localhost:9200/mweibo/_settings -d '{
"index" : {
    "number_of_replicas" : 0
}

作者:星火燎原智勇
原文链接:www.cnblogs.com/liang1101/articles...
}’

讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!