【Elasticsearch入门】Elasticsearch集群管理

1、集群节点监控

在 Elasticsearch的运行期间,一个很重要的方面就是监控。这使得系统管理员能够检测并预防可能性的问题,或至少知道失败时会发生什么。 Elasticsearch提供了非常详细的信息,使你能够检査和监控单个节点或一个整体的集群。包括集群的健康值、有关服务器的信息、节点信息、索引和分片信息等。对 Elasticsearch监控的API主要有三类:一类是集群相关的,以 _cluster开头,第二类是监控节点相关的,以 _nodes开头,第三类是任务相关的,以 _tasks开头。

1.1、集群健康值

集群健康值可以通过集群健康检查 API _cluster/health得到简单情况。

GET http://127.0.0.1:9200/_cluster/health/

返回值:

如果请求的后面加上索引的名称,则可以得到这个索引的健康检查情况。例如:

GET http://127.0.0.1:9200/_cluster/health/secisland?pretty=true
返回值中, status字段提供的值反应了集群整体的健康程度,它的状态是由系统中最差的分片决定的。值的意义如下:

  • green——所有的主分片(Primary Shard)和副本分片(Replica shard)都处于活动状态。
  • yellow——所有的主分片都处于活动状态,但是并不是所有的副本分片都处于活动状态。
  • red——不是所有的主分片都处于活动状态。

1.2、集群状态

整个集群的综合状态信息是可以通过 _cluster/state参数查询的。

GET http://127.0.0.1:9200/_cluster/state/

返回值:

默认情况下,集群状态请求的是主节点的状态。在 state后面增加 metadata只请求索引结构相关的信息,如果后面加上具体的索引,则只请求这个具体索引结构相关的信息。
例如:其他的几个例子:

1.3、集群统计

集群统计 API _cluster/stats可以从一个集群的角度来统计集群状态。它返回两个最基本的信息,一个是索引的信息,比如分片的数量、存储的大小、内存的使用等;另一个是集群节点的信息,比如节点数量、角色、操作系统信息、JVM版本、内存使用率、CPU
和插件的安装信息。
请求GET http://127.0.0.1:9200/_cluster/stats
返回值:

1.4、集群任务管理

集群任务管理接口是2.3.0新增接口,这个接口是实验性质的,未来有可能会改变。
请求如下:

返回值:

任务应用接口还可以用来等待任务的完成,下面的调用将等待10秒或ID为oTUltx4IQMOUUVeiohTt8A:123的任务等待10秒:

需要长时间等待的任务可以用下面的接口取消,取消操作可以取消一个或者多个任务:

1.5、待定集群任务

待定集群任务接口返回一个尚未执行的集群水平变化的列表,例如,创建索引、更新映射、分配分片或失败分片。
GET http://127.0.0.1:9200/_cluster/pending_tasks
它通常返回空,因为系统正常情况下处理是很快的。

1.6、节点信息

集群节点信息接口用于搜索一个或多个集群节点信息。节点信息的接口参数为 _nodes。
请求:GET http:127.0.0.1:9200/_nodes
返回值:

从指标上来看,有 settings、os、 process, Jvm、 thread_pool、 transport、http和 plugins。

和集群统计类似,也可以在最后面加上指标信息,对关注的指标单独查看,比如nodes/os只査看操作系统信息。

活跃线程查看
通过 _nodes/hot_threads接口查询活跃线程,在 _nodes后面加上节点名可以查询某个节点上的活跃线程。
请求:GET http:27.0.0.1:9200/_nodes/hott_hreads
或者请求具体某个节点:GEt http:270.0.1:9200/_nodes/{nodeslds}/hott_hreads

1.7、节点统计

集群节点统计AP可以对一个、多个或全部的集群节点进行统计。例如:

GET http://127.0.0.1:9200/_nodes/Artemis/stats/
Artemis是节点名称,多个节点可以用逗号分开。这个命令把所有的统计信息都返回了,可以在最后面加上指标,只返回你关注指标的统计,多个指标可以用逗号分开,例如:
GET http://127.0.0.1:9200/_nodes/Artemis/stats/os,fs
上面的命令只返回节点中操作系统和文件系统的信息,统计指标解释如下:

  • indices——索引相关的数据统计,包括size、 document count、 indexing and deletion
  • times、 search times、 field cache size、 merges and flushes
  • fs——文件系统信息,包括路径、磁盘空间、读/写数据等。
  • http——Http连接信息。
  • jvm——JVM虚拟机的统计,包括内存池的数据、垃圾回收、缓冲池一些加载/卸载类等。
  • os——操作系统统计,平均负载、内存、交换分区等。
  • process——进程统计,包括内存消耗、处理器使用、打开文件描述符等。
  • thread_pool——线程池的统计,包括当前大小、队列和拒绝。的任务等。
  • transport——网络数据统计,集群通信中发送和接收字节的统计。
  • breaker——数据处理的统计。
  • script——脚本相关的信息。

2、集群分片迁移

在 Elasticsearch中可以通过集群路由 API _cluster/reroute来对集群中的分片进行操作,例如可以在集群中把一个分片从一个节点迁移到另一个节点,将未分配的分片可以分配到个特定节点上等。不过要想完全手动,必须先把 cluster.routing.allocation.disable_allocation参数设置为true,禁止ES进行自动索引分片分配,否则你从A节点把分片移到B节点,那么另外一个节点的一个分片又会移到A节点。语法如下

一共有三种操作移动(move)、取消(cancel)和分配(allocate)。下面分别介绍这三种情况:

  • 移动(move)——把分片从一节点移动到另一个节点。可以指定索引名和分片号。
  • 取消(cancel)——取消分配一个分片。可以指定索引名和分片号。node参数可以指定在哪个节点取消正在分配的分片。 allow_primary参数支持取消分配主分片。
  • 分配( allocate)——分配一个未分配的分片到指定节点,可以指定索引名和分片号。node参数指定分配到哪个节点; allow_primary参数可以强制分配主分片,不过这样可能导致数据丢失。因为 allow_primary参数将使一个新的空主分片被分配,如果有一份原始的分片副本(包括数据)的节点重新加入集群,分片副本数据将被删除:旧的分片副本将会被新的活动分片副本替换。

集群配置更新:系统允许对集群的配置进行更新。配置更新有两种状态,一是持久的二是临时的,例如:
请求:PUT127.0.0.1:9200/_cluster/settings
{"persistent":{"discovery.zen.minimum_master_nodes": 2}}
上面的例子是持久更新配置,如果把参数 persistent换成了 transient,就是临时更新。

3、集群节点配置

当我们启动 Elasticsearch的实例,就会启动至少一个节点。相同集群名的多个节点的连接就组成了一个集群,在默认情况下,集群中的每个节点都可以处理HTTP请求和集群节点的数据传输。集群中所有的节点都知道集群中其他所有的节点,可以将客户端请求转发到适当的节点。节点有以下类型:

  • 主(master)节点:在一个节点上当 node.master设置为true(默认)的时候,它有资格被选作为主节点,控制整个集群。
  • 数据(data)节点:在一个节点上 node.data设置为true(默认)的时候。该节点保存数据和执行数据相关的操作,如增删改查、搜索和聚合。默认情况下,节点同时是主节点和数据节点,这是非常方便的小集群,但随着集群的发展,分离主节点和数据节点将变得非常重要。
  • 客户端节点:当一个节点的 node.master和 node.data都设置为 false的时候,它既不能保持数据也不能成为主节点,该节点可以作为客户端节点,可以响应用户的请求,并把相关操作发送到其他节点。
  • 部落节点:当一个节点配置 tribe.*的时候,它是一个特殊的客户端,它可以连接多个集群,在所有连接的集群上执行搜索和其他操作。

客户端节点在搜索请求或批量增加索引请求等可能涉及在不同数据节点上的操作。这些请求会分成两个阶段,一是接收客户端的请求,二是协调节点执行相关操作。当数据分散在不同的节点上时,协调节点将请求转发到数据节点,每个数据节点在本地执行请求并把结果传输给协调节点,然后协调节点收集各个数据节点的结果转换成单个请求结果返回。所以需要客户端有足够的内存和CPU来处理各个节点的返回结果。

3.1、主节点

主节点的主要职责是和集群操作相关的内容,如创建或删除索引,跟踪哪些节点是集群的一部分,并决定哪些分片分配给相关的节点。稳定的主节点对集群的健康是非常重要的。
默认情况下任何一个集群中的节点都有可能被选为主节点。索引数据和搜索查询等操作会占用大量的CPU、内存、IO资源,为了确保一个集群的稳定,分离主节点和数据节点是一个比较好的选择。
虽然主节点也可以协调节点,搜索路由和从客户端新增数据到数据节点,但最好不要使用这些专用的主节点。一个重要的原则是,尽可能做少量的工作。创建一个独立的主节点的配置如下:

node.master: true
node.data: false

为了防止数据丢失,配置 discovery.zen.minimum_master_nodes是至关重要的(默认为1),每个主节点应该知道形成一个集群的最小数量的主资格节点的数量。解释一下。
假设我们有一个集群,有3个主节点,当网络发生故障的时候,有可能其中一个节点不能和其他节点进行通信了。这个时候,当 discovery.zen.minimum_master_nodes设置为1时,就会分成两个小的独立集群,当网络好的时候,就会出现数据错误或者丢失数据的情况。当discovery.zen.minimum_master_nodes设置为2的时候,一个网络中有两个主节点,可以继续工作,另一部分,由于只有一个主资格节点,则不会形成一个独立的集群,这个时候当网络回复的时候,节点又会重新加入集群。设置这个值的原则是:
(master_eligible_nodes /2 )+1

这个参数也可以动态设置:
PUT http:127.0.0.1:9200/_cluster/settings
{"transient":{"discovery.zen.minimum_master_nodes":2}}

3.2、数据节点

数据节点主要是存储索引数据的节点,主要对文档进行增删改查、聚合操作等。数据节点对CPU、内存、IO要求较高,在优化的时候需要监控数据节点的状态,当资源不够的时候,需要在集群中添加新的节点。数据节点的配置如下:

node.master: false
node.data: true

3.3、客户端节点

当主节点和数据节点配置都设置为 false时,该节点只能处理路由请求,处理搜索,分发索引操作等,从本质上来说该客户端节点表现为智能负载平衡器。独立的客户端节点在一个比较大的集群中是非常有用的,它协调主节点和数据节点,客户端节点加入集群可以得到集群的状态,根据集群的状态可以直接发送路由请求。

添加大多的客户端节点对集群是一种负担,因为主节点必须等待每一个节点集群状态的更新确认!客户端节点的作用不应被夸大,数据节点也可以起到类似的作用。
配置如下:

node.master: false
node.data: false

数据节点路径设置:每一个主节点和数据节点都需要知道分片、索引、元数据的物理存储位置, path.data默认位为$ES_HOME/data,可以通过配置文件 elasticsearch.ym进行修改,例如:

path.data: /var/elasticsearch/data
这个设置也可以在命令行上执行,例如:
elasticsearch --path.data /var/elasticsearch/data
这个路径最好进行单独配置,这样 Elasticsearch的目录和数据的目录就会分开。当删除了 Elasticsearch主目录的时候,不会影响到数据。通过rpm安装默认是分开的。
数据目录可以被多个节点共享,甚至可以属于不同的集群,为了防止多个节点共享相同的数据路径,可以在配置文件elasticsearch.yml中添加: node.max_local_storage_nodes:1

在相同的数据目录不要运行不同类型的节点(例如: master、data、client),这会导致意外的数据丢失。

3.4、部落节点

部落节点可以跨越多个集群,它可以接收每个集群的状态,然后合并成一个全局集群的状态,它可以读写所有节点上的数据,部落节点在 elasticsearch.yml中的配置如下

tribe:
    t1:
        cluster.name: cluster_one
    t2:
        cluster.name: cluster_two

T1和T2是任意的名字,代表连接到每个集群。上面的示例配置两个集群连接,名称分别是T1和T2。默认情况下,部落节点通过单播发现来连接每一个集群。用于连接的任何其他设置可以配置在 tribe{name}后,就像上面的例子。大多数情况下,部落节点可以像单节点一样对集群进行操作。
注意,以下操作将和单节点操作不同,如果两个集群的名称相同,部落节点只会连接其中一个。
由于没有主节点,主节点级别的读操作如:集群统计、集群健康度,会在本地标志设置为true的节点自动执行。
主节点级别的写操作将被拒绝,如创建索引,这些操作应该在单个集群节点上执行。

部落节点可以通过块( block)设置所有的写操作和所有的元数据操作,例如:

tribe:
    blocks:
        write: true
        metadata: true

部落节点也可以在选中的索引块中单独配置以上操作,例如:

tribe:
    blocks:
        write.indices: hk*,ldn*
        metadata_indices: hk*,ldn*

当多个集群有相同的索引名的时候,默认情况下,部落节点将选择其中一个。这可以通过 tribe.on_conflict_setting进行配置,可以设置排除那些索引或者指定固定的部落名称。

4、节点发现

在 Elasticsearch中,节点之间可以相互发现,并把相同集群名称的节点统一成一个集群,那节点是如何发现的呢,这次就谈一下节点发现的一些内部细节。在 Elasticsearch内部,zen发现机制是默认的发现模块。它提供了单播发现方式,能够很容易地扩展至云环境。
发现模块和其他模块集成,例如所有节点的通信是通过传输模块。发现模块分成两个模块:

  • ping模块,通过ping模块可以寻找其他节点。
  • 单播模块,需要提供一个主机列表作为路由列表。以 discovery.zen.ping.unicast作为前缀。

主机列表设置: hosts,配置全路径为: discovery.zen.ping.unicast.hosts。它是一个数组的配置,多个主机设置以逗号分开。格式为 host:port,或者 host[port1-por2],ip6的主机必须放在方括号内,例如127.0.0.1,[::1]。
单播发现依赖传输模块实现。注意port默认端口是9300。

下面介绍主节点选举过程。

4.1、主节点选举

在集群中,系统会自动通过ping来进行选举主节点或者加入主节点,这些都是自动完成的:

  • discovery.zen.ping_timeout(默认3秒)配置允许对选举的时间进行调整,用来处理缓慢或拥挤的网络。当一个节点请求加入主节点,它会发送请求信息到主节点,请求的超时时间配置为 discovery.zen.join_timeout,这个时间比较长,是 discovery.zen.ping_timeout时间的20倍。当主节点发生问题的时候,现有的节点又会通过png来重新选举一个新的主节点。当 discovery.zen.master_election.filter_client设置为true的时候,在选举主节点的时候从客户端节点(node.client为tue或者node.data和 node.master同时为 false)的ping操作将被忽略,该参数默认为tues当 discovery.zen.master.election.filter_data为true时,在选举主节点的时候从数据节点(node.data为ture, node_master同时为 false)的ping操作将被忽略,默认为 false。主节点配置为tue的节点一直都有选举的资格。当节点 node.master设置为 false或者node.client设置为true的时候,它们将自动排除成为主节点的可能性。
  • discovery.zen.minimum_master_nodes设置需要加入一个新当选的主节点的最小节点数目,或者接收它作为主节点的最小节点数。如果不满足这一要求,主节点会下台,重新开始新的选举。

4.2、故障检测

有两种方式进行故障检测,第一个是由主节点到所有其他节点的验证,证明它们还活着。另一种,是每个节点ping主节点验证,当主节点有故障的时候会启动选举过程。控制故障检测过程使用 discovery.zen.fd前缀设置:

  • ping_interval:ping检查的频率(时间间隔),默认值为1秒。
  • ping_timeout:ping的超时时间,默认为30秒。
  • ping_retries:多少次ping失败或者超时的节点被认为是失败的。默认3次。

主节点是在一个集群中可以改变集群状态的唯一节点。主节点处理一个集群状态的更新,适用于所需的更改,并将更新的集群状态发布到集群中的所有其他节点上。每个节点接收发布消息,更新它自己的集群状态,并对主节点进行应答,该主节点等待所有节点响应,然后在处理下一个更新的队列前进行超时处理。 discovery.zen.publish_timeout默认为30秒,可以通过动态配置进行设置。
一个健康的集群必须有一个主节点,并且有多个满足主节点选举条件的节点,这个数字由 discovery.zen.minimum_master_nodes设置。 discovery.zen.no_master_block设置没有有效的主节点时应拒绝的操作,有两个选择:

  • all:这个节点上的所有行为被拒绝,包括读写,同时拒绝集群状态的读写操作,比如得到索引设置。
  • write:基于最后一次的集群配置,写操作被拒绝,允许读操作。这可能会导致部分读取的数据是过期的,因为这个节点已经从集群中分离,这个是默认设置。

discovery.zen.no_master_block设置不适用于基于节点状态的API例如 cluster stats、node info和 node stats。

5、集群平衡配置

一个主节点的主要作用是决定哪些分片分配给哪个节点,并在节点之间移动分片以平衡整个集群。有很多设置可以控制分片的分配过程

  • 分片分配设置——可以通过设置来对集群进行分配和再平衡操作。
  • 基于磁盘的配置——可以根据可用磁盘空间大小来进行分配设置。
  • 分片智能分配——可以控制分片在不同的机架或可用性区域中的配置。
  • 分片配置过滤——允许某些节点或节点组排除在分配的列表中,常用在需要停止的节点中。

在本节中的所有设置都是动态设置,可以通过集群接口进行实时更新。

5.1、分片分配设置

分片分配过程是分片到节点的一个处理过程,它可能发生在初始恢复过程中,副本分配中,再平衡过程中,或当节点被添加或删除时。

5.1.1、分片分配设置

下面的动态设置可以用来控制分片的分配和回收。

  • cluster.routing.allocation.enable:禁用或启用哪种类型的分片,可选的参数有:all——允许所有的分片被重新分配。primaries——只允许主结点分片被重新分配。new_primaries——只允许新的主结点索引的分片被重新分配。none——不对任何分片进行重新分配。
  • cluster.routing.allocation.node_concurrent_recoveries:允许在一个节点上同时并发多少个分片分配,默认为2。
  • cluster.routing.allocation.node_initial_primaries_recoveries:当副本分片加入集群的时候,在一个节点上并行发生分片分配的数量,默认是4个。
  • cluster.routing.allocation.same_shard.host:在一个主机上的当有多个相同的集群名称的分片分配时,是否进行检查,检查主机名和主机ip地址。默认为 false,此设置仅适用于在同一台机器上启动多个节点时配置。
  • indices.recovery.concurrent_streams:从一个节点恢复的时候,同时打开的网络流量的数量,默认为3。
  • indices.recovery.concurrent_small_file_streams:从同伴的分片恢复时打开每个节点的小文件(小于5M)流的数目,默认为2。

5.1.2、分片平衡设置

下面的动态设置可以用来控制整个集群的碎片再平衡,配置有:

  • cluster.routing.rebalance.enable:启用或禁用特定种类的分片重新平衡,可选的参数有
  1. all——允许所有的分片进行分片平衡,默认配置。
  2. primaries——只允许主分片进行平衡。
  3. replicas——只允许从分片进行平衡。
  4. none——不允许任何分片进行平衡。
  • cluster.routing.allocation.allow_rebalance:当分片再平衡时允许的操作,可选的参数有:
  1. always——总是允许再平衡。
  2. indices_primaries_active——只有主节点索引允许再平衡。
  3. indices_all_active——所有的分片允许再平衡,默认参数。
  4. cluster.routing.allocation.cluster_concurrent_rebalance:重新平衡时允许多少个并发的分片同时操作,默认为2。

5.1.3、启发式分片平衡

以下设置用于确定在何处放置每个碎片的数据:

  • cluster.routing.allocation.balance.shard:在节点上分配每个分片的权重,默认是0.45。
  • cluster.routing.allocation.balance.index:在特定节点上,每个索引分配的分片的数量,默认0.55
  • cluster.routing.allocation.balance.threshold:操作的最小最优化的值。默认为1。

5.2、基于磁盘的配置

Elasticsearch可以根据磁盘的大小来决定是否重新进行分片的分配。有如下配置

cluster.routing.allocation.disk.threshold_enabled:是否启用磁盘分配决策,默认为true。
cluster.routing.allocation.disk.watermark.low:允许分配时的磁盘空间最小值,可以是比例或者绝对值,比如85%或者1G。当磁盘占用超过设定的值之后,系统将不会对此节点进行分配操作。
cluster.routing.allocation.disk.watermark.high:允许保存分片节点磁盘空间的最大值,当超过这个值后,系统会把分片迁移到别的节点。默认90%。也可以设置一个具体的大小值(比如500mb)当可用空间小于这个值的时候,系统会自动迁移分片到别的节点。
cluster.info.update.interval:检查集群中每个节点的磁盘使用情况的时间间隔,默认30秒。
cluster.routing.allocation.disk.include_relocations:当计算节点的磁盘使用时需要考虑当前被分片的情况。默认为true。

比如下面的一个配置实例

实例的含义是,每分钟检查一下磁盘空间,当磁盘已用空间小于80%的时候参与分片分配,当可用空间不足5GB的时候,将节点的分片迁移到别的节点。
需要注意的是,在2.0.0版本前,当系统有多个数据盘的时候,系统考虑的是总大小,在2.0.0版本之后,系统考虑的是每个磁盘的使用情况。

5.3、分片智能分配

实际部署时,很多时候是部署在虚拟机中,共享同一个物理节点,或者部署的时候在同一个机架、同一个网络区域中。当这些情况下遇到故障时,很多节点会同时发生故障,导致系统出现问题。如果在配置 Elasticsearch的时候事先能够注意到把不同的节点分布在不同的物理机器、不同的机架或者不同的网络区域中,这样当一个节点出现问题的时候,会使风险降到最低。
区域分片分配(Shard Allocation Awareness设置用于配置 Elasticsearch关于硬件的信息,例如,我们在启动的时候在启动程序后面加上--node.rack_id,后面跟上一个指定的名称,这个配置也可以放在配置文件中:
elasticsearch --node.rack_id rack_one

同时我们需要设置 cluster.routing.allocation.awareness.attributes: rack_id,可以在配置文件中设置,或者通过 cluster-update-settings API接口设置。

假设有两个节点 node.rack_id的名称都为 rack_one,我们创建一个索引有5个主要的分片和一个副本分片。将所有的主分片和副本分片分配在两个节点上。然后我们新加两个节点,节点 node.rack_id的名称为 rack_two。这样配置后,系统会自动分配主分片到新的节点上,确保没有两个相同的分片在同一个区域中。
当搜索的时候,系统会智能地处理,只在一个区域中搜索,这样会比在不同的区域中搜索更快。

当使用区域分片分配属性,碎片不会分配给没有设置这些属性的值的节点。具有相同区域属性值的一组节点中主/副本分片的数量由属性值的数量决定。当一组节点的数量是不平衡的,并且有许多的副本,可能会产生未赋值的副本分片。
强制分配属性,解决了不允许相同的分片副本被分配到同一区域的问题。假设当我们有两个区域的时候,每个区域的大小只够分配一半的分片,如果一个区域不可用,全部分片都在一个区域会导致空间不够,引起系统异常,这个时候,强制分配属性就有意义了。示例配置如下:
cluster.routing.allocation.awareness.force.zone.values: zone1, zone2
cluster.routing.allocation.awareness.attributes: zone
这个时候,如果我们启动了 zone l上的两个节点,并创建有5个主分片一个副本分片的索引,这个时候在zone1上只会启动主分片,只到zone2的节点启动后,才会启动副本分片。

5.4、分片配置过滤

分片配置过滤可以对索引的分片分配进行控制,允许或禁止分配到指定节点。这个功能用在集群级别分片分配过滤上,可在移除节点之前把节点上的分片移动到其他节点中。例如我们想停止10.0.0.1这个IP上的所有节点,可如下操作
请求:PUT http://127.0.0.1:9200/_cluster/settings
{"transient":{"cluster.routing.allocation.exclude._ip":"10.0.0.1"}}
这样正常情况下,10.0.0.1节点上的分片会被迁移到其他节点。动态配置的属性如下:
cluster.routing.allocation.include.{attribute}:将索引分配给一个节点,其{attribute}至少有一个逗号分隔的值。
cluster.routing.allocation.require.{attribute}:将索引分配给一个节点,该节点的{attribute}具有所有的逗号分隔值。
cluster.routing.allocation.exclude.{attribute}:将索引分配给一个节点,其{attribute}没有一个逗号分隔的值。

attributes可以包含的值有

  • name——通过节点名称匹配节点。
  • _ip——通过P地址匹配节点。
  • host——通过机器名称匹配节点。

所有的属性值可以用通配符,如:
PUT http://127.0.0.1:9200/_cluster/settings
{"transient ":{"cluster.routing.allocation.include._ip":"192. 168.2.*"}}

5.5、其他集群配置

还有一些集群配置如下。
只读设置:可以设置 cluster.blocks.read_only使整个集群为只读。
日志记录:设置日志记录的级别,例如增加了 indices.recovery模块,其日志记录级别的调试代码如下
PUT http://127.0.0.1:9200/_cluster/settings
{"transient":("logger.indices.recovery ":"DEBUG"}}

6、分布式存储

文档最终会存储在分片上,如图所示:

Document1是如何存储到分片P1的呢?选择P1的依据是什么呢?
需要文档到分片的映射算法
目的:使得文档均匀分布在所有分片上,以充分利用资源。
算法:随机选择或者round-robin算法。
不可取:因为维护文档到分片的映射关系,成本巨大。

6.1、文档到分片的映射算法

es通过如下公司计算文档对应的分片
shard = hash(routing) % number_of_primary_shards
hash算法保证可以将数据均匀地分散在分片中。
routing是一个关键参数,默认是文档id,也可以自行指定。
number_of_primary_shards 是主分片数。
该算法与主分片数相关,这也是分片数一旦确定后便不能更改的根本原因。

6.2、文档创建的流程

6.3、文档读取的流程

7、文档搜索的实时性

7.1、倒排索引不可变

倒排索引一旦生成,不能更改

有如下好处:

  • 不用考虑并发写文件的问题,杜绝了锁机制带来的性能问题
  • 由于文件不再更改,可以充分利用文件系统缓存,只需要载入一次,只要内存足够,对该文件的读取都会从内存读取,性能高
  • 利于生成缓存数据
  • 利于对文件进行压缩存储,节省磁盘和内存存储空间

坏处:

7.2、解决方案

新文档直接生成新的倒排索引文件,查询的时候同时查询所有的倒排文件,然后对查询结果做汇总计算即可。

Lucene采用了这种方案,它构建的单个倒排索引称为segment,合在一起称为Index,与ES中的Index概念不同。ES中的一个Shard对应一个Lucene Index。Lucene会有一个专门的文件来记录所有的segment信息,称为Commit Point。

7.3、Refresh

segment写入磁盘的过程依然很耗时,可以借助文件系统缓存的特性,先将segment在缓存中创建并开放查询来进一步提升实时性,该过程在es中被称为refresh。
在refresh之前文档会先存储在一个buffer中,refresh时将buffer中的所有文档清空并生成segment。es默认每1秒执行一次refresh,因此文档的实时性被提高到1秒,这也是es被称为近实时(Near Real Time)的真正原因。

refresh发生的时机主要有以下几种情况:
间隔时间达到时,通过index.settings.refresh_interval来设定,默认是1秒
index.buffer占满时,其大小通过indices.memory.index_buffer_size设置,
默认为jvm heap的10%,所有shard共享
flush发生时也会发生refresh

7.4、Translog

如果在内存中的segment还没有写入磁盘前发生了宕机,那么内存中的文档就无法恢复了。

那么如何解决这个问题呢?
es引入translog机制。写入文档到buffer时,同时将该操作写入translog。translog 文件会即时写入磁盘(fsync),6.x默认每个请求都会落盘,可以修改为每5秒写一次,这样风险便是丢失5秒内的数据,相关配置为index.translog.*。es重新启动时会自动检查translog文件,并从中恢复数据。

  • 写入新文档时,必须重新构建倒排索引文件,然后替换老文件后,新文档才能被检索,
  • 导致文档实时性受到影响

7.5、Flush

flush负责将内存中的segment写入磁盘,主要做如下的工作:

  1. 将translog写入磁盘
  2. 将index buffer清空,其中的文档生成一个新的segment,相当于一个refrsh操作
  3. 更新commit point并写入磁盘
  4. 执行fsync操作,将内存中的segment写入磁盘
  5. 删除旧的translog文件

flush发生的时机主要有以下几种情况:
间隔时间达到时,默认是30分钟,5.x之前可以通过index.translog.flush_threshold_period修改,之后发布的版本无法设置。
translog占满时,其大小可以通过index.translog.flush_threshold_size控制,默认是512MB,每个index有自己的translog。

7.6、删除与更新

segment一旦生成就不能更改,那么如果要删除文档该如何操作?
lucene会专门维护一个.del的文件,记录所有已经删除的文档,注意.del上记录的是文档在Lucene的内部id,在查询结果返回前会过滤掉.del中所有的文档。

更新文档如何进行呢?
首先删除文档,然后再创建新的文档。

7.7、整体视角

7.8、Segment Merging

随着segment的增多,由于一次查询的segment数增多,查询速度会变慢,es会定时在后台进行segment merge的操作,减少segment的 数量,通过force_merge api可以手动强制做segment merge的操作。
 


 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值