ElasticSearch 发现机制

发现机制介绍与配置 该模块主要负责集群中节点的自动发现和Master节点的选举。节点之间使用p2p的方式进行直接通信,不存在单点故障的问题。Elasticsearch中,Master节点维护集群的全局状态,比如节点加入和离开时进行shard的重新分配。 自动发现机制在目前版本(1.3.1)提供了四种选择,一种是默认实现,其他都是通过插件实现。

  1. Azure discovery 插件方式,多播
  2. EC2 discovery 插件方式,多播
  3. Google Compute Engine (GCE)discovery 插件方式多播
  4. zen discovery默认实现 多播/单播

多播配置下,节点向集群发送多播请求,其他节点收到请求后会做出响应。配置参数如下:

discovery.zen.ping.multicast.group:224.2.2.4 组地址
discovery.zen.ping.multicast.port:54328 端口
discovery.zen.ping.multicast.ttl:3 广播消息ttl
discovery.zen.ping.multicast.address:null绑定的地址,null表示绑定所有可用的网络接口
discovery.zen.ping.multicast.enabled:true 多播自动发现禁用开关

单播配置下,节点向指定的主机发送单播请求,配置如下:

discovery.zen.ping.unicast.hosts:host1:port1,host2,:port2

选举Master节点: 在ping主节点过程中,节点会加入到集群中或者会被选举为主节点,发送主节点的超时时间有餐宿discovery.zen.join_timeout来控制,默认为3s,对于配置node.master为false的节点启动后不会作为主节点的候选。discovery.zen.minimum_master_nodes配置当前集群中最少的主节点数,对于多于两个节点的集群环境,建议配置大于1。

故障检测: 一般存在两个故障检测过程。第一个是主节点周期性的ping其他节点。第二就是其他节点周期的ping主节点。相关参数:

ping_interval:1s节点被ping的频率
ping_timeout:30s等待ping返回的时间
ping_timeout:3重试次数,超过该次,就认为该节点不可用

分布式以及 Elastic

分布式系统要解决的第一个问题就是节点之间互相发现以及选主的机制。如果使用了 Zookeeper/Etcd 这样的成熟的服务发现工具,这两个问题都一并解决了。但 Elasticsearch 并没有依赖这样的工具,带来的好处是部署服务的成本和复杂度降低了,不用预先依赖一个服务发现的集群,缺点当然是将复杂度带入了 Elasticsearch 内部。

服务发现以及选主ZenDiscovery

节点启动后先ping(这里的ping是 Elasticsearch 的一个RPC命令。如果 discovery.zen.ping.unicast.hosts 有设置,则ping设置中的host,否则尝试ping localhost 的几个端口, Elasticsearch 支持同一个主机启动多个节点) Ping的response会包含该节点的基本信息以及该节点认为的master节点。选举开始,先从各节点认为的master中选,规则很简单,按照id的字典序排序,取第一个。如果各节点都没有认为的master,则从所有节点中选择,规则同上。这里有个限制条件就是 discovery.zen.minimum_master_nodes,如果节点数达不到最小值的限制,则循环上述过程,直到节点数足够可以开始选举。 最后选举结果是肯定能选举出一个master,如果只有一个local节点那就选出的是自己。如果当前节点是master,则开始等待节点数达到 minimum_master_nodes,然后提供服务。如果当前节点不是master,则尝试加入master。 Elasticsearch 将以上服务发现以及选主的流程叫做 ZenDiscovery 。由于它支持任意数目的集群(1-N),所以不能像 Zookeeper/Etcd 那样限制节点必须是奇数,也就无法用投票的机制来选主,而是通过一个规则,只要所有的节点都遵循同样的规则,得到的信息都是对等的,选出来的主节点肯定是一致的。但分布式系统的问题就出在信息不对等的情况,这时候很容易出现脑裂(Split-Brain)的问题,大多数解决方案就是设置一个quorum值,要求可用节点必须大于quorum(一般是超过半数节点),才能对外提供服务。而 Elasticsearch 中,这个quorum的配置就是 discovery.zen.minimum_master_nodes 。 说到这里要吐槽下 Elasticsearch 的方法和变量命名,它的方法和配置中的master指的是master的候选节点,也就是说可能成为master的节点,并不是表示当前的master,我就被它的一个 isMasterNode 方法坑了,开始一直没能理解它的选举规则。

弹性伸缩 Elastic

Elasticsearch 的弹性体现在两个方面: 1. 服务发现机制让节点很容易加入和退出。 2. 丰富的设置以及allocation API。

Elasticsearch 节点启动的时候只需要配置discovery.zen.ping.unicast.hosts,这里不需要列举集群中所有的节点,只要知道其中一个即可。当然为了避免重启集群时正好配置的节点挂掉,最好多配置几个节点。节点退出时只需要调用 API 将该节点从集群中排除 (Shard Allocation Filtering),系统会自动迁移该节点上的数据,然后关闭该节点即可。当然最好也将不可用的已知节点从其他节点的配置中去除,避免下次启动时出错。

分片(Shard)以及副本(Replica) 分布式存储系统为了解决单机容量以及容灾的问题,都需要有分片以及副本机制。Elasticsearch 没有采用节点级别的主从复制,而是基于分片。它当前还未提供分片切分(shard-splitting)的机制,只能创建索引的时候静态设置。

比如上图所示,开始设置为5个分片,在单个节点上,后来扩容到5个节点,每个节点有一个分片。如果继续扩容,是不能自动切分进行数据迁移的。官方文档的说法是分片切分成本和重新索引的成本差不多,所以建议干脆通过接口重新索引。

Elasticsearch 的分片默认是基于id 哈希的,id可以用户指定,也可以自动生成。但这个可以通过参数(routing)或者在mapping配置中修改。当前版本默认的哈希算法是MurmurHash3。

Elasticsearch 禁止同一个分片的主分片和副本分片在同一个节点上,所以如果是一个节点的集群是不能有副本的。

恢复以及容灾

分布式系统的一个要求就是要保证高可用。前面描述的退出流程是节点主动退出的场景,但如果是故障导致节点挂掉,Elasticsearch 就会主动allocation。但如果节点丢失后立刻allocation,稍后节点恢复又立刻加入,会造成浪费。Elasticsearch的恢复流程大致如下:

集群中的某个节点丢失网络连接 master提升该节点上的所有主分片的在其他节点上的副本为主分片 cluster集群状态变为 yellow ,因为副本数不够 等待一个超时设置的时间,如果丢失节点回来就可以立即恢复(默认为1分钟,通过 index.unassigned.node_left.delayed_timeout 设置)。如果该分片已经有写入,则通过translog进行增量同步数据。 否则将副本分配给其他节点,开始同步数据。 但如果该节点上的分片没有副本,则无法恢复,集群状态会变为red,表示可能要丢失该分片的数据了。

分布式集群的另外一个问题就是集群整个重启后可能导致不预期的分片重新分配(部分节点没有启动完成的时候,集群以为节点丢失),浪费带宽。所以 Elasticsearch 通过以下静态配置(不能通过API修改)控制整个流程,以10个节点的集群为例:

gateway.recover_after_nodes: 8 gateway.expected_nodes: 10 gateway.recover_after_time: 5m 比如10个节点的集群,按照上面的规则配置,当集群重启后,首先系统等待 minimum_master_nodes(6)个节点加入才会选出master, recovery操作是在 master节点上进行的,由于我们设置了 recover_after_nodes(8),系统会继续等待到8个节点加入, 才开始进行recovery。当开始recovery的时候,如果发现集群中的节点数小于expected_nodes,也就是还有部分节点未加入,于是开始recover_after_time 倒计时(如果节点数达到expected_nodes则立刻进行 recovery),5分钟后,如果剩余的节点依然没有加入,则会进行数据recovery。

results matching ""

    No results matching ""