【ES】入门

ES集群构成

首先,一个Elasticsearch集群是由许多节点(Node)构成的,Node可以有不同的类型,通过以下配置,可以产生四种不同类型的Node:

conf/elasticsearch.yml:
    node.master: true/false
    node.data: true/false

四种不同类型的Node是一个node.master和node.data的true/false的两两组合。当然还有其他类型的Node,比如IngestNode(用于数据预处理等),不在本文讨论范围内。

当node.master为true时,其表示这个node是一个master的候选节点,可以参与选举,在ES的文档中常被称作master-eligible node,类似于MasterCandidate。ES正常运行时只能有一个master(即leader),多于1个时会发生脑裂。

当node.data为true时,这个节点作为一个数据节点,会存储分配在该node上的shard的数据并负责这些shard的写入、查询等。

此外,任何一个集群内的node都可以执行任何请求,其会负责将请求转发给对应的node进行处理,所以当node.master和node.data都为false时,这个节点可以作为一个类似proxy的节点,接受请求并进行转发、结果聚合等。
在这里插入图片描述
上图是一个ES集群的示意图,其中NodeA是当前集群的Master,NodeB和NodeC是Master的候选节点,其中NodeA和NodeB同时也是数据节点(DataNode),此外,NodeD是一个单纯的数据节点,Node_E是一个proxy节点。每个Node会跟其他所有Node建立连接。

节点发现

ZenDiscovery是ES自己实现的一套用于节点发现和选主等功能的模块,没有依赖Zookeeper等工具,官方文档:

https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-discovery-zen.html

简单来说,节点发现依赖以下配置:

conf/elasticsearch.yml:
    discovery.zen.ping.unicast.hosts: [1.1.1.1, 1.1.1.2, 1.1.1.3]

这个配置可以看作是,在本节点到每个hosts中的节点建立一条边,当整个集群所有的node形成一个联通图时,所有节点都可以知道集群中有哪些节点,不会形成孤岛。

官方推荐这里设置为所有的master-eligible node,读者可以想想这样有何好处:

It is recommended that the unicast hosts list be maintained as the list of master-eligible nodes in the cluster.

Master选举

上面提到,集群中可能会有多个master-eligible node,此时就要进行master选举,保证只有一个当选master。如果有多个node当选为master,则集群会出现脑裂,脑裂会破坏数据的一致性,导致集群行为不可控,产生各种非预期的影响。

为了避免产生脑裂,ES采用了常见的分布式系统思路,保证选举出的master被多数派(quorum)的master-eligible node认可,以此来保证只有一个master。这个quorum通过以下配置进行配置:

conf/elasticsearch.yml:
    discovery.zen.minimum_master_nodes: 2
这个配置对于整个集群非常重要。

1.master选举谁发起,什么时候发起?

master选举当然是由master-eligible节点发起,当一个master-eligible节点发现满足以下条件时发起选举:

  1. 该master-eligible节点的当前状态不是master。
  2. 该master-eligible节点通过ZenDiscovery模块的ping操作询问其已知的集群其他节点,没有任何节点连接到master。
  3. 包括本节点在内,当前已有超过minimum_master_nodes个节点没有连接到master。

总结一句话,即当一个节点发现包括自己在内的多数派的master-eligible节点认为集群没有master时,就可以发起master选举。

2.当需要选举master时,选举谁?

  1. 当clusterStateVersion越大,优先级越高。这是为了保证新Master拥有最新的clusterState(即集群的meta),避免已经commit的meta变更丢失。因为Master当选后,就会以这个版本的clusterState为基础进行更新。(一个例外是集群全部重启,所有节点都没有meta,需要先选出一个master,然后master再通过持久化的数据进行meta恢复,再进行meta同步)。
  2. 当clusterStateVersion相同时,节点的Id越小,优先级越高。即总是倾向于选择Id小的Node,这个Id是节点第一次启动时生成的一个随机字符串。之所以这么设计,应该是为了让选举结果尽可能稳定,不要出现都想当master而选不出来的情况。
ClusterStateVersion是集群的状态版本号,
每一次集群选举ClusterStateVersion都会更新,
因此最大的ClusterStateVersion是与原有集群数据最接近或者是相同的,这样就尽可能的避免了数据丢失。

3.什么时候选举成功?

当一个master-eligible node(我们假设为Node_A)发起一次选举时,它会按照上述排序策略选出一个它认为的master。

  • 假设Node_A选Node_B当Master:

Node_A会向Node_B发送join请求,那么此时:

(1) 如果Node_B已经成为Master,Node_B就会把Node_A加入到集群中,然后发布最新的cluster_state, 最新的cluster_state就会包含Node_A的信息。相当于一次正常情况的新节点加入。对于Node_A,等新的cluster_state发布到Node_A的时候,Node_A也就完成join了。

(2) 如果Node_B在竞选Master,那么Node_B会把这次join当作一张选票。对于这种情况,Node_A会等待一段时间,看Node_B是否能成为真正的Master,直到超时或者有别的Master选成功。

(3) 如果Node_B认为自己不是Master(现在不是,将来也选不上),那么Node_B会拒绝这次join。对于这种情况,Node_A会开启下一轮选举。

  • 假设Node_A选自己当Master:

此时NodeA会等别的node来join,即等待别的node的选票,当收集到超过半数的选票时,认为自己成为master,然后变更cluster_state中的master node为自己,并向集群发布这一消息。

源码-选举流程-简介

假如集群中有3个master-eligible node,分别为Node_A、 Node_B、 Node_C, 
选举优先级也分别为Node_A、Node_B、Node_C。三个node都认为当前没有master,
于是都各自发起选举,选举结果都为Node_A(因为选举时按照优先级排序,如上文所述)。
于是Node_A开始等join(选票),Node_B、Node_C都向Node_A发送join,当Node_A接收到一次join时,
加上它自己的一票,就获得了两票了(超过半数),于是Node_A成为Master。
此时cluster_state(集群状态)中包含两个节点,当Node_A再收到另一个节点的join时,
cluster_state包含全部三个节点。

4.选举保证不脑裂

首先为避免在一个选举周期内,Node A投出2票的情况

比如raft算法中就引入了选举周期(term)的概念,保证了每个选举周期中每个成员只能投一票,
如果需要再投就会进入下一个选举周期,term+1。假如最后出现两个节点都认为自己是master,
那么肯定有一个term要大于另一个的term,而且因为两个term都收集到了多数派的选票,
所以多数节点的term是较大的那个,保证了term小的master不可能commit任何状态变
更(commit需要多数派节点先持久化日志成功,由于有term检测,不可能达到多数派持久化条件)。
这就保证了集群的状态变更总是一致的。

错误检测

  • 心跳检测
    一类是Master定期检测集群内其他的Node,另一类是集群内其他的Node定期检测当前集群的Master。检查的方法就是定期执行ping请求。
  • rejoin
    除了上述两种情况,还有一种情况是Master发现自己已经不满足多数派条件(>=minimumMasterNodes)了,需要主动退出master状态(退出master状态并执行rejoin)以避免脑裂的发生,那么master如何发现自己需要rejoin呢?
  1. 上面提到,当有节点连不上时,会执行removeNode。在执行removeNode时判断剩余的Node是否满足多数派条件,如果不满足,则执行rejoin。
  2. 在publish新的cluster_state时,分为send阶段和commit阶段,send阶段要求多数派必须成功,然后再进行commit。如果在send阶段没有实现多数派返回成功,那么可能是有了新的master或者是无法连接到多数派个节点等,则master需要执行rejoin。
  3. 在对其他节点进行定期的ping时,发现有其他节点也是master,此时会比较本节点与另一个master节点的cluster_state的version,谁的version大谁成为master,version小的执行rejoin。

集群扩缩容

1 扩容DataNode

假设一个ES集群存储或者计算资源不够了,我们需要进行扩容,这里我们只针对DataNode,即配置为:

conf/elasticsearch.yml:
    node.master: false
    node.data: true

然后需要配置集群名、节点名等其他配置,为了让该节点能够加入集群,我们把discovery.zen.ping.unicast.hosts配置为集群中的master-eligible node。

conf/elasticsearch.yml:
    cluster.name: es-cluster
    node.name: node_Z
    discovery.zen.ping.unicast.hosts: ["x.x.x.x", "x.x.x.y", "x.x.x.z"]

然后启动节点,节点会自动加入到集群中,集群会自动进行rebalance,或者通过reroute api进行手动操作。

2 缩容DataNode

假设一个ES集群使用的机器数太多了,需要缩容,我们怎么安全的操作来保证数据安全,并且不影响可用性呢?

首先,我们选择需要缩容的节点,注意本节只针对DataNode的缩容,MasterNode缩容涉及到更复杂的问题,下面再讲。

然后,我们需要把这个Node上的Shards迁移到其他节点上,方法是先设置allocation规则,禁止分配Shard到要缩容的机器上,然后让集群进行rebalance。

PUT _cluster/settings
{
  "transient" : {
    "cluster.routing.allocation.exclude._ip" : "10.0.0.1"
  }
}

等这个节点上的数据全部迁移完成后,节点可以安全下线。

3 扩容MasterNode

ES

1.ES为什么快?

ES 采用的是倒序索引。
对比传统数据库,用类似ID的键位做查询条件,速度很快,但对于全文检索来说,就很尴尬,
比如like %name%,这样就走不到索引了,需要全表查询。对于ES的倒序索引来说,就很快。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值