学会偷懒,并懒出效率

ElasticSearch集群分片原理

今天分享一下ElasticSearch集群分片原理,玩好集群,分片原理就得明白怎么回事?如果分片原理都不清楚,那么如何玩好ElasticSearch集群?

1、空集群

如果我们启动了一个单独的节点,里面不包含任何的数据和 索引,那我们的集群看起来就是一个 “包含空内容节点的集群”。

一个运行中的 Elasticsearch 实例称为一个 节点,而集群是由一个或者多个拥有相同 cluster.name 配置的节点组成, 它们共同承担数据和负载的压力。当有节点加入集群中或者从集群中移除节点时,集群将会重新平均分布所有的数据。

2、拥有一个索引的单节点集群

在包含一个空节点的集群内创建名为 blogs 的索引。 索引在默认情况下会被分配5个主分片和1个副分片, 但是为了演示目的,我们将分配3个主分片和一份副本。
注意:3个主分片都有一个副分片,此时分片总数为:6片,不是4片哦。

提示:创建索引时指定的主分片数以后是无法修改的,所以主分片数的数量要根据项目决定。副分片数以后是可以修改的。

如上图:P0、P1、P2共3个主分片,为什么没有副分片呢?这是因为只有一个节点没必要生成分片,一个节点挂掉,副分片也会挂掉,完全还是单故障,故Elasticsearch自动不生成副分片。

3、拥有两个节点的集群

当第二个节点加入到集群后,3个 副本分片 将会分配到这个节点上——每个主分片对应一个副本分片。 这意味着当集群内任何一个节点出现问题时,我们的数据都完好无损。

所有新近被索引的文档都将会保存在主分片上,然后被并行的复制到对应的副本分片上。这就保证了我们既可以从主分片又可以从副本分片上获得文档。

如上图可以看出,当集群中第2台加入时,此时P0=>R0、P1=>R1、P2=>R2这3个副分片生成,这样集群中有1台挂掉,另一台还是完整的数据,这样就避免了单点故障。

4、拥有三个节点的集群

目前集群中有Node1、Node2,试想一下如果有一天流量上去了,这两台压力太大了,需要扩容,那么我们另入第3个节点,为了分散负载而对分片进行重新分配,如下图:


从上图可以看出,P0主分片从Node1=>Node3,R2副分片从Node2=>Node3了。这样这3个节点同时都有2个分片,如果有一个节点挂掉就会回到拥有2个节点的集群。这样集群容错更高,负载能力更强了。可能有人会问,为什么没有生成更多的副分片,这是因为我们创建索引的时候指定了1个副分片,3个主分片。所以这里已经有1个副分片了。所以系统自动把每个节点平分2个分片。不知道我解释清楚了没。我相信你们能懂的。
那么我们这个集群(3个主分片,1个副分片)最大能用几台服务器呢?由上图可知我们最多扩容到6台服务器,P1、P2、P3、R0、R1、R2每一个在一台服务器上。试想一下如果有一天我们的业务量远大于6台服务器所承载的流量。那么我们如何扩容呢?

5、将集群副分片设置成2

之前我们说过,副分片数是可以重设的,这时我们将参数 number_of_replicas 调大到 2,还接着上面3个节点的例子向下说吧,如下图:

如上图副分片由原来的1变成了2,所以就自动复制出一个副分片。此时集群共有9个分片,每个节点有3个分片。这样更好的提高了故障,比如有任何2台挂掉,剩下的那一台还是完整的数据。

6、关闭了一个节点后的集群

假如现在Node1节点关掉了,那么集群是如何处理的?

由上图我们可知,原先在Node1上的分片R0、P1、P2挂掉了,那么Node2、Node3上得有一个节点选举出主节点P1、P2才能保证集群的完整性。通过系统选举最后Node2上的R2=>P2,Node3上的R1=>P1保证了集群的完整性,此时的集群状态是yellow。

为什么我们集群状态是 yellow 而不是 green 呢?因为我们设置的是2个副分片,现在副分片数是不对的。 所以集群不能为 green 的状态,不过我们不必过于担心:如果我们同样关闭了 Node 2 ,我们的程序 依然 可以保持在不丢任何数据的情况下运行,因为 Node 3 为每一个分片都保留着一份副本,当然Node1如果重新加入集群,那么集群就成green了。

7、主副分布如何交互

新建、索引和删除单个文档


1、客户端向 Node 1 发送新建、索引或者删除请求。
2、节点使用文档的 _id 确定文档属于分片 0。请求会被转发到 Node 3,因为分片 0 的主分片目前被分配在Node 3 上。
3、Node 3 在主分片上面执行请求。如果成功了,它将请求并行转发到 Node 1 和 Node 2 的副本分片上。一旦所有的副本分片都报告成功, Node 3 将向协调节点报告成功,协调节点向客户端报告成功。

取回单个文档


1、客户端向 Node 1 发送获取请求。
2、节点使用文档的 _id 来确定文档属于分片 0 。分片 0 的副本分片存在于所有的三个节点上。 在这种情况下,它将请求转发到 Node 2 。
3、Node 2 将文档返回给 Node 1 ,然后将文档返回给客户端。
为了读取请求,协调节点在每次请求的时候将选择不同的副本分片来达到负载均衡;通过轮询所有的副本分片。

局部更新文档


1、客户端向 Node 1 发送更新请求。
2、它将请求转发到主分片所在的 Node 3 。
3、Node 3 从主分片检索文档,修改 _source 字段中的 JSON ,并且尝试重新索引主分片的文档。 如果文档已经被另一个进程修改,它会重试步骤 3 ,超过 retry_on_conflict 次后放弃。
4、如果 Node 3 成功地更新文档,它将新版本的文档并行转发到 Node 1 和 Node 2 上的副本分片,重新建立索引。 一旦所有副本分片都返回成功, Node 3 向协调节点也返回成功,协调节点向客户端返回成功。