elasticsearch 集群(概念认知)

  • ES的集群是什么
  • 集群由什么组成
  • 集群能干什么用
  • 集群怎么做到的
  • 集群的优点是什么

集群内的原理

ElasticSearch 的主旨是随时可用和按需扩容。 而扩容可以通过购买性能更强大( 垂直扩容 ,或 纵向扩容 scale up) 或者数量更多的服务器( 水平扩容 ,或 横向扩容 scale out )来实现。

虽然 Elasticsearch 可以获益于更强大的硬件设备,但是垂直扩容是有极限的。 真正的扩容能力是来自于水平扩容—​为集群添加更多的节点,并且将负载压力和稳定性分散到这些节点中

概念

cluster: 集群 node:节点 shard: 分片 replica: 副本

  • 节点: 一个运行中的Elasticsearch实例称之为一个节点。
  • 主节点: 负责管理集群范围的所有变更,增加或删除索引和增加或删除节点。主节点是被选举出来的,这点后面单独写,可以跟kafka的节点选举,进行比较一下。
  • 集群:由一个或者多个拥有相同cluster.name的配置节点组成,它们共同承担数据和负载的压力。当有节点加入集群中或者从集群中移除节点时,集群将会重新平均分布所有的数据。
  • 空集群: 启动了一个单独的节点,里面不包含任何数据和索引。
  • 分片:见下文
  • 副本分片:见下文

节点

  1. 主节点:Master Node,;主节点负责轻量级的集群范围的操作,例如创建或删除索引,跟踪哪些节点是集群的一部分,并决定将哪些分片分配给哪些节点。对于集群运行状况来说,拥有一个稳定的主节点非常重要。

    node.roles: [ master ]
  2. 数据节点:Data Node 数据节点保存包含已建立索引的文档的分片。数据节点处理与数据相关的操作,如CRUD、搜索和聚合。这些操作是I/O、内存和cpu密集型的。监视这些资源并在它们过载时添加更多数据节点非常重要。一个节点即可是数据节点,也可以是候选主节点(Master-eligible node)
    好处:使用专用数据节点的主要好处是将主角色和数据角色分离

    node.roles: [ data ]

    3.预处理节点: Ingest node 预处理节点可以执行预处理管道,它由一个或多个 预处理 处理器组成。根据 预处理 处理器执行的操作类型和所需的资源,可能有必要使用专用的 预处理 节点,这些节点只执行特定的任务

    node.roles: [ ingest ]
  3. 客户端节点:client node
    客户端节点就是既不做候选主节点也不做数据节点的节点,只负责请求的分发、汇总等等,
    也就是下面要说到的协调节点的角色。这样的工作,其实任何一个节点都可以完成,
    单独增加这样的节点更多是为了负载均衡

    node.roles: [这个在7.14官方文档没搜到怎么配置] //TODO
  4. 协调节点:Coordinating node,协调节点 该节点只能路由请求、处理搜索减少阶段和分发批量索引。本质上,协调节点作为智能负载均衡器。协调节点可以使大型集群受益,因为它将协调节点的角色从 数据节点 和 候选主节点 中卸下。它们加入集群并接收完整的集群状态,就像每个其他节点一样,它们使用集群状态将请求直接路由到适当的位置;
    虽然对节点做了角色区分,但是用户的请求可以发往任何一个节点,并由该节点负责分发请求、收集结果等操作,而不需要主节点转发,这种节点可称之为协调节点,协调节点是不需要指定和配置的,集群中的任何节点都可以充当协调节点的角色
    缺点:增加太多的协调节点,会增加整个集群的负担,当选的主节点必须等待来自每个节点的集群状态更新的确认

    node.roles: [ ] # 这个就这样配置 空的数组
  5. 还有其他节点类型,虽然不常见,但需要知道:

Remote-eligible node:
默认情况下,集群中的任何节点都可以作为跨集群客户端连接到远程集群。连接后,可以使用跨集群搜索搜索远程集群。还可以使用跨集群复制在集群之间同步数据

node.roles: [ remote_cluster_client ]

Transform node 转换节点 运行转换并处理转换API请求

node.roles: [ transform ]

Hot data node
热数据节点在进入Elasticsearch时存储时间序列数据。热层必须能够快速读写,并且需要更多的硬件资源(如SSD驱动器)。

node.roles: [ data_hot ]

Warm data Node:热(翻译为预热数据)数据节点存储的索引不再定期更新,但是仍旧会被请求,查询量的频率通常低于索引在热层(tier 等级,层,行)时的频率
Machine Learning Node:机器学习特性提供机器学习节点,运行作业和处理机器学习API请求

node.roles: [ data_warm ]
xpack.ml.enabled: true

code data node
冷数据节点存储访问频率较低的只读索引

node.roles: [ data_cold ]

Frozen data node
冻结层只存储部分挂载的索引

node.roles: [ data_frozen ]

脑裂

脑裂现象
同时如果由于网络或其他原因导致集群中选举出多个Master节点,使得数据更新时出现不一致,这种现象称之为脑裂,即集群中不同的节点对于master的选择出现了分歧,出现了多个master竞争。

"脑裂"可能的原因:

  • 网络问题:集群间的网络延迟导致一些节点访问不到master,认为master挂掉了从而选举出新的master,并对master上的分片和副本标红,分配新的主分片

  • 节点负载:主节点的角色既为master又为data,访问量较大时可能会导致ES停止响应(假死状态)造成大面积延迟,此时其他节点得不到主节点的响应认为主节点挂掉了,会重新选取主节点。

  • 内存回收:主节点的角色既为master又为data,当data节点上的ES进程占用的内存较大,引发JVM的大规模内存回收,造成ES进程失去响应

分片 shard

  • 当es索引上的数据量太大的时候,会通过水平拆分的方式将一个索引上的数据拆分出来,分配到不同的数据块上,拆分出来的数据块称之为一个分片

tips:我们的文档被存储和索引到分片内,但是应用程序是直接与索引而不是与分片进行交互。

分片本身就是一个完整的搜索引擎(es中的一个分片其实是Lucene的一个实例, 【lucene是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎】),它可以使用单一节点的所有资源

  • 主分片:用于解决数据水平扩展的问题,一个索引的主分片数量只能在创建时指定,后期无法修改,除非对数据进行重新构建索引(reindex操作)。主分片的数目决定着索引能够保存的最大数据量。理论上说一个主分片最大能够存储 Integer.MAX_VALUE(2 147 483 647) - 128 个文档
  • 副本分片:只是一个主分片的拷贝。
    • 副本分片作为硬件故障时保护数据不丢失的冗余备份,并为搜索和返回文档等读操作提供服务。
    • 用于解决数据高可用的问题,在索引建立的时候就已经确定了主分片数,但是副本分片数可以随时修改副本分片数的最大值是 n -1(其中 n 为节点数)。
  • 数据写入的时候是写到主分片,副本分片会复制主分片的数据;
    主分片或者复制分片都可以处理读请求——搜索或文档检索,所以数据的冗余越多,能处理的搜索吞吐量就越大。
  • 分片是数据的容器,文档保存在分片内,分片又被分配到集群内的各个节点里。当你的集群规模扩大或者缩小时, Elasticsearch 会自动的在各节点中迁移分片,使得数据仍然均匀分布在集群里。
PUT /blogs
{
   "settings" : {
      "number_of_shards" : 3, #默认是5个主分片,这里分配3个主分片
      "number_of_replicas" : 1 # 设置1个副本,每个主分片拥有一个副本分片
   }
}

集群健康

GET /_cluster/health
其中字段指示着当前集群在总体上是否工作正常。它的三种颜色含义如下:

  • green
    所有的主分片和副本分片都正常运行。
  • yellow
    所有的主分片都正常运行,但不是所有的副本分片都正常运行。
  • red
    有主分片没能正常运行
{
  "cluster_name" : "es",
  "status" : "green",
  "timed_out" : false,
  "number_of_nodes" : 2,
  "number_of_data_nodes" : 2,
  "active_primary_shards" : 8, #8个主分片
  "active_shards" : 16,#所有的分片,主分片和副本分片
  "relocating_shards" : 0,#显示当前正在从一个节点迁往其他节点的分片的数
  "initializing_shards" : 0,#是刚刚创建的分片的个数
  "unassigned_shards" : 0,
  "delayed_unassigned_shards" : 0,
  "number_of_pending_tasks" : 0,
  "number_of_in_flight_fetch" : 0,
  "task_max_waiting_in_queue_millis" : 0,
  "active_shards_percent_as_number" : 100.0
}

unassigned_shards 是已经在集群状态中存在的分片,但是实际在集群里又找不着。通常未分配分片的来源是未分
配的副本。比如,一个有 5 分片和 1 副本的索引,在单节点集群上,就会有 5 个未分配副本分片。
如果你的集群是 red 状态,也会长期保有未分配分片(因为缺少主分片)

实例分析

{
"cluster_name" : "es",
"status" : "red",
"timed_out" : false,
"number_of_nodes" : 2,
"number_of_data_nodes" : 2,
"active_primary_shards" : 8,
"active_shards" : 16,
"relocating_shards" : 0,
"initializing_shards" : 0,
"unassigned_shards" : 8,
"delayed_unassigned_shards" : 0,
"number_of_pending_tasks" : 0,
"number_of_in_flight_fetch" : 0,
"task_max_waiting_in_queue_millis" : 0,
"active_shards_percent_as_number" : 100.0
}
上述 "unassigned_shards" : 8,代表有8个未分片,是一个索引里缺少8个主分片,还是4个索引里各1主1副本?具体是哪个
GET _cluster/health?level=indices 这个命令可以查看到你想知道的。此外还有
GET _cluster/health?level=shards

集群选举

选举流程7.x版本之前选举

  • 对所有可以成为master的节点根据nodeId排序,每次选举每个节点都把自己所知道节点排一次序,然后选出第一个(第0位)节点,暂且认为它是master节点。

  • 如果对某个节点的投票数达到一定的值(可以成为master节点数n/2+1)并且该节点自己也选举自己,那这个节点就是master。否则重新选举。

  • 对于脑裂问题,需要把候选master节点最小值设置为可以成为master节点数n/2+1(quorum)

  • 选举时间点
    1 集群启动初始化
    2 集群master崩溃
    3 任何一个节点发现当前集群中的Master节点没有得到n/2 + 1节点认可的时候,触发选举

  • 选举各个阶段
    1 筛选activeMasters列表
    Elasticsearch节点成员首先向集群中的所有成员发送Ping请求,针对获取的全部response进行过滤,筛选出其中activeMasters列表,activeMaster列表是其它节点认为的当前集群的Master节点
    2 筛选masterCandidate列表
    masterCandidates列表是当前集群有配置为候选主节点的节点 node.roles : [master]
    3 从activeMasters列中选举Master节点
    选举算法是bully算法,如果列不为空,从中选举,选择id最小的节点
    3.1 如果activeMasters为空,那么会在masterCandidate选举,先看是否达到了最小数目discovery.zen.minimum_master_nodes,如果达到的情况下比较优先级,优先级比较的时候首先比较节点拥有的集群状态版本编号,然后再比较id,这一流程的目的是让拥有最新集群状态的节点成为master
    4 本地节点成为master
    会选举出一个准master节点, 准master节点会等待其它节点的投票,如果有discovery.zen.minimum_master_nodes-1个节点投票认为当前节点是master,那么选举就成功,准master会等待discovery.zen.master_election.wait_for_joins_timeout时间,如果超时,那么就失败

5 本地节点不是master
当前节点判定在集群当前状态下如果自己不可能是master节点,
首先会禁止其他节点加入自己,然后投票选举出准Master节点。
同时监听master发布的集群状态(MasterFaultDetection机制),如果集群状态显示的master节点和当前节点认为的master节点不是同一个节点,那么当前节点就重新发起选举。

非Master节点也会监听Master节点进行错误检测,如果成员节点发现master连接不上,重新加入新的Master节点,如果发现当前集群中有很多节点都连不上master节点,那么会重新发起选举。

总结:
ping所有节点,并获取PingResponse返回结果(findMaster)
过滤出具有Master资格的节点(filterPingResponses)
选出临时Master。根据PingResponse结果构建两个列表:activeMasters和masterCandidates。
– 如果activeMasters非空,则从activeMasters中选择最合适的作为Master;
– 如果activeMasters为空,则从masterCandidates中选举,结果可能选举成功,也可能选举失败。
判断临时Master是否是本节点。
– 如果临时Master是本节点:则等待其他节点选我,默认30秒超时,成功的话就发布新的clusterState。(当选总统候选人,只等选票过半了)
– 如果临时Master是其他节点:则不再接受其他节点的join请求,并向Master节点发送加入请求。(没资格选举,就只能送人头了)

es7.x版本之后的选举流程

7.x之后的ES,采用-种新的选主算法Raft [rɑːft] n. 筏;救生艇。具体算法之前写过,Raft协议leader选举

简述:
Raft选举流程为:

增加当前节点本地的current term,切换到Candidate状态;
当前节点投自己一票,并且并行给其他节点发送RequestVote RPC (让大家投他) ;

然后等待其他节点的响应,会有如下三种结果:

如果接收到大多数服务器的选票,那么就变成Leader。成为Leader后,向其他节点发送心跳消息来确定自己的地位并阻止新的选举。
如果收到了别人的投票请求,且别人的term比自己的大,那么候选者退化为Follower;
如果选举过程超时,再次发起一轮选举;

ES实现Raft算法选主流程
ES实现中,候选人不先投自己,而是直接并行发起RequestVote,这相当于候选人有投票给其他候选人的机会。这样的好处是可以在一定程度上避免3个节点同时成为候选人时,都投自己,无法成功选主的情况

ES不限制每个节点在某个term上只能投一票, 节点可以投多票,这样会产生选出多个主的情况:

Node2被选为主,收到的投票为:Node2、 Node3;
Node3被选为主,收到的投票为:Node3、 Node1;
对于这种情况,ES的处理是让最后当选的Leader成功,作为Leader。如果收到RequestVote请求,他会无条件退出Leader状态。

上图中,Node2先被选为主,随后他收到Node3的RequestVote请求,那么他退出Leader状态,切换为CANDIDATE,并同意向发起RequestVote候选人投票。因此最终Node3成功当选为Leader。还真是与世无争啊这node2

动态维护参选节点列表

  • 在7.x之前的版本中,用户需要手工配置minimum_master_nodes, 来明确告诉集群过半节点数应该是多少,并在集群扩缩容时调整他
  • 7.x之后的版本,记录仪个节点列表,保存了所有具备master资格的节点,VotingConfiguration
  • 在节点加入或离开集群之后,Elasticsearch 会自动对VotingConfiguration 做出相应的更改,以确保集群具有尽可能高的弹性

在节点加入或离开集群之后,Elasticsearch 会自动对VotingConfiguration 做出相应的更改,以确保集群具有尽可能高的弹性。在从集群中删除更多节点之前,等待这个调整完成是很重要的。你不能一次性停止半数或更多的节点。(感觉大面积缩容时候这个操作就比较感人了,一部分一部分缩)。默认情况下,ES自动维护VotingConfiguration。有新节点加入的时候比较好办,但是当有节点离开的时候,他可能是暂时的重启,也可能是永久下线。你也可以人工维护VotingConfiguration,配置项为:cluster.auto_shrink_voting_configuration,当你选择人工维护时,有节点永久下线,需要通过voting exclusions API将节点排除出去。如果使用默认的自动维护VotingConfiguration,也可以使用voting exclusions API来排除节点,例如一次性下线半数以上的节点。

如果在维护VotingConfiguration时发现节点数量为偶数,ES会将其中一个排除在外,保证VotingConfiguration是奇数。因为当是偶数的情况下,网络分区将集群划分为大小相等的两部分,那么两个子集群都无法达到“多数”的条件

具体操作

POST /_cluster/voting_config_exclusions?node_names=<node_names>
POST /_cluster/voting_config_exclusions?node_ids=<node_ids>
DELETE /_cluster/voting_config_exclusions

Adds nodes named nodeName1 and nodeName2 to the voting configuration exclusions list:

POST /_cluster/voting_config_exclusions?node_names=nodeName1,nodeName2

Remove all exclusions from the list:

DELETE /_cluster/voting_config_exclusions

机制原理

主分片和副本分片是如何同步的?
创建索引的流程是什么样的?
ES如何将索引数据分配到不同的分片上的?
以及这些索引数据是如何存储的?
为什么说ES是近实时搜索引擎而文档的 CRUD (创建-读取-更新-删除) 操作是实时的?
以及Elasticsearch 是怎样保证更新被持久化在断电时也不丢失数据?
还有为什么删除文档不会立刻释放空间?


若知后事如何,且听下文分解

参考链接 :https://blog.csdn.net/weixin_42257250/article/details/90230017
https://blog.csdn.net/zwgdft/article/details/54585644
https://cloud.tencent.com/developer/article/1826421?from=article.detail.1826426
https://cloud.tencent.com/developer/article/1826426

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注