ES

ElastricSearch第二弹之分片原理

2021-03-30  本文已影响0人  阿Q说代码

最近好多小伙伴后台留言想看ES的后续内容,今天它来了,废话不多说,直接上干货。

首先让我们来了解一下 ES 中的分片概念:ES 支持 PB 级全文搜索,当索引上的数据量太大的时候,ES 通过水平拆分的方式将一个索引上的数据拆分出来分配到不同的数据块上,分布在多台服务器上存储,拆分出来的数据库块称之为一个分片。分片是一个功能完整的搜索引擎,它拥有使用一个节点上的所有资源的能力。这类似于 MySQL 的分库分表,在一个多分片的索引中写入数据时,通过路由来确定具体写入哪一个分片中,所以在创建索引的时候需要指定主分片的数量,并且主分片的数量一旦确定就不能修改(原因在下文中介绍),副本分片可以动态修改。

那么什么是主分片?什么是副本分片呢?

分片的数量和副本数量都是可以通过创建索引时的 Settings 来配置,ES 默认为一个索引创建 5 个主分片, 并分别为每个分片创建一个副本分片。

PUT /myIndex
{
   "settings" : {
      "number_of_shards" : 5,
      "number_of_replicas" : 1
   }
}
为什么要分片?为什么要区分主副分片呢?

ES 通过分片的功能使得索引在规模上和性能上都得到提升,有了 shard 就可以横向扩展,存储更多数据,让搜索和分析等操作分布到多台服务器上去执行,提升吞吐量和性能。

读操作:搜索和返回数据可以同时被主分片或副本分片所处理,所以当你拥有越多的副本分片时,也将拥有越高的吞吐量;

区分主副分片的原因:任何一个服务器随时可能故障或宕机,此时shard可能就会丢失,如果为每个 shard 创建 replica 副本,当 shard 所在的服务器不可用时,replica 可以提供备用服务,这样就保证了 ES 在失去某个节点的情况下不丢失任何数据。

举例说明

假设这时节点 Node1 服务宕机了或者网络不可用了,那么主节点上主分片 S0 也就不可用了。幸运的是还存在另外两个节点能正常工作,这时 ES 会重新选举新的主节点,而且这两个节点上存在我们所需要的 S0 的所有数据。我们会将 S0 的副本分片提升为主分片,这个提升主分片的过程是瞬间发生的。此时集群的状态将会为 Yellow。为什么我们集群状态是 Yellow 而不是 Green 呢?虽然我们拥有所有的 2 个主分片,但是同时设置了每个主分片需要对应两份副本分片,而此时只存在一份副本分片。所以集群不能为 Green 的状态。如果我们同样关闭了 Node2 ,我们的程序依然可以保持在不丢失任何数据的情况下运行,因为 Node3 为每一个分片都保留着一份副本。如果我们重新启动 Node1 ,集群可以将缺失的副本分片再次进行分配,那么集群的状态又将恢复到原来的正常状态。如果 Node1 依然拥有着之前的分片,它将尝试去重用它们,只不过这时 Node1 节点上的分片不再是主分片而是副本分片了,如果期间有更改的数据只需要从主分片上复制修改的数据文件即可。

知识点补充:

集群状态通过 绿,黄,红 来标识:

写索引原理:主分片和副本分片的同步原理

写索引是只能写在主分片上,然后同步到副本分片。
写操作:对文档的新建、索引和删除请求,必须在主分片上面完成之后才能被复制到相关的副本分片。

如图所示,上图中有3个节点,4个主分片,8个副本分片,一条数据 ES 是根据什么规则写到特定分片上的呢?首先这肯定不会是随机的,否则将来要获取文档的时候我们就不知道从何处寻找了。实际上,这个过程是根据下面这个公式决定的:

shard = hash(routing) % number_of_primary_shards

Routing 是一个可变值,默认是文档的_id,也可以设置成一个自定义的值。Routing 通过 Hash 函数生成一个数字,然后这个数字再除以 number_of_primary_shards (主分片的数量)后得到余数。这个在 0 到 number_of_primary_shards-1 之间的余数,就是我们所寻求的文档所在分片的位置。这就解释了为什么我们要在创建索引的时候就确定好主分片的数量并且永远不会改变这个数量。因为如果数量变化了,那么所有之前路由的值都会无效,文档也再也找不到了。由于在 ES 集群中每个节点通过上面的计算公式都知道集群中的文档的存放位置,所以每个节点都有处理读写请求的能力。在一个写请求被发送到某个节点后,该节点即为前面说过的协调节点,协调节点会根据路由公式计算出需要写到哪个分片上,再将请求转发到该分片的主分片节点上。

ES 为了提高写入的能力这个过程是并发写的,同时为了解决并发写的过程中数据冲突的问题,ES 通过乐观锁的方式控制,每个文档都有一个 _version (版本)号,当文档被修改时版本号递增。一旦所有的副本分片都报告写成功才会向协调节点报告成功,协调节点向客户端报告成功。

举例说明

假如此时数据通过路由计算公式取余后得到的值是 shard=hash(routing)%4=0。
则具体流程如下:

副本分片是越多越好吗?

答案当然是 no ,原因有以下两点:

总结:

阿Q正在将ES的知识做一个系统的学习与讲解,后续还会持续输出ES的相关知识,如果你感兴趣的话,可以关注gzh“阿Q说”!你也可以后台留言说出你的疑惑,阿Q将会在后期的文章中为你解答。

上一篇 下一篇

猜你喜欢

热点阅读