elasticsearch分片交互过程

es如何存储数据到分片中

当我们要在ES中存储数据的时候,数据应该存储在主分片和复制分片中的哪一个去;当我们再ES中检索数据的时候,有时怎么判断要查询的数据属于哪一个分片?

  • 数据存储到分片的过程是一定规则的,并不是随机发生的
  • 规则:shard=hash(routeing)% number_of_primary_shards
  • routing值可以是一个任意的字符串,默认情况下,它的值为数据对应文档的_id值,也可以是用户自定义的值。routing这个字符串通过一个hash函数的处理,并返回一个数值,然后通过除以索引中的分片的数目,得到的余数作为主分片的编号,取值一般在0到number_of_primary_shards-1的这个范围中,通过这种方法计算出该数据是存储到哪个分片中
  • 正是这种路由机制,导致了主分片的个数问什么在索引建立之后不能修改。对已有索引主分片数目的修改会直接导致路由规则出现严重的问题,部分数据无法被检索

例如索引与删除一个文档

这俩种过程均可以分为三个过程来描述

  1. 客户端发送了一个索引或者删除的请求给node1
  2. node1,通过文档中的_id判断改值被存储在shard 0这个分片中,并且node1知道shard0的primary shard位于node3这个节点上。因此node1会把这个请求转发给node3
  3. node3在shard0的primary shard上执行请求。如果请求执行成功,它node3将并行请求发给shard0的所有replica shard上,也就是存在于node1和node2的replica shard。如果所有的replica shard都成功执行了请求,那么将会向node3回复一个成功确认,当node3收到了所有replica shard的确认信息后,则最后向用户返回一个success消息

更新一个文档

  1. 客户端向node 1发送一个文档更新的请求。
  2. 同样的node 1通过请求中文档的 _id 值判断出该文档应该被存储在shard 0 这个分片中,并且node 1知道shard 0的primary shard位于node 3这个节点上。因此node 1会把这个请求转发到node 3。
  3. _node 3从文档所在的primary shard中获取到它的JSON文件,并修改其中的_source中的内容,之后再重新索引该文档到其primary shard中。
  4. 如果node 3成功地更新了文档,node 3将会把文档新的版本并行地发给其余所有的replica shard所在node中。这些node也同样重新索引新版本的文档,执行后则向node 3确认成功,当node 3接收到所有的成功确认之后,再向客户端发送一个更新成功的信息。

检索文档

CRUD这些操作的过程中一般都是结合一些唯一的标记列如:_index,_type以及routing的值,这就意味着在执行操作的时候都是确切知道文档在集群的哪个node中,哪个shard中

而检索过程往往需要更多的执行模式,因为我们并不清楚所要检索的文档具体的位置所在,它们可能存在于ES集群中任何位置。因此一般情况下,索引的执行不得不去询问index中的每一个shard

但是,找到所有匹配检索的文档仅仅是检索过程的一半,在向客户端返回一个结果列表之前,必须将各个shard发回的小片的解锁结果,拼接成一个大的已排好序的汇总结果列表。正因为这个原因,蒋所分为查询阶段和获取阶段(Query Phase and Fetch Phase)

Query Phase

在最初的查询过程中,查询请求会广播到index中的每一个primary shard和replica shard中,每一个shard会在本地执行检索,并建立一个优先级队列(priority queue)在优先级队列是一个根据文档匹配度这个指标所排序列表,列表的长度由分页参数from和size俩个参数决定的

query phase阶段可以再细分为3个小的子阶段

  1. 客户端发送一个检索的请求给node3,此时node3会创建一个空的优先级队列并配置好分页参数from与size
  2. node3架构检索请求发送给index中每一个shard(这里的每一个意思是无论它是primary还是replica,它们可以构成一个完整的index数据)。每个shard在本地执行检索,并将结果添加到本地优先级队列中
  3. 每个shard返回本地优先级序列中所记录的_id与sort值,并发送node3.node3将这些值合并到自己本地的优先级队列中,并做全局排序

Fetch Phase

Qeury Phase主要定位了所要检索数据的具体位置,但是我们还必须取回它们才能完成整个检索过程。而Fetch Phase阶段的任务就是将这些定位好的数据内容取回并返回给客户端。

Fetch Phase 过程可以分为三个子过程来描述

  1. node3获取了所有待检索的数据定位之后,发送一个mget的请求给数据库相关的shard
  2. 每个受到node3的get请求的shard将读取相关文档_source中的内容,并将它们返回给node3
  3. 当node3获取到了所有shard返回的文档后,node3将它们合并成一条汇总的结果,返回给客户端

ES数据的分片策略

称谓

Cluster

集群,一个ES集群是由多个节点Node组成的,每个集群都有一个cluster name 作为标识

cluster.name: 【elastic search cluster name】

在同一网段下的Elastic search实例会通过cluster name决定加入哪个集群下

node

节点,一个ES实例就是一个node,一个机器可以由多个实例,并不是说一台机器就是一个node,大多数环境下,每个node运行在一个独立的环境或者虚拟机上

index

索引:即一些列documents的集合

shard

  1. 分片,ES是分别是搜索引擎,每个索引有一个或多个分片,索引的数据被分配到各个分片上,相当于一桶水,用了N个杯子装
  2. 分片有助于横向扩展,N个分片会尽可能平均分配到不同的节点上(例如俩个节点四个主分片不考虑备份,,那么每个节点会分到2个分片,后来你增加了2个节点,那么你这4个节点上都会有1个分片,这个过程叫relocation,ES感知后自动完成)
  3. 分片是独立的,对于一个Search Reuqest 的行为每个分片都会执行这个Request
  4. 每个分片都是一个lucene Index所以一个分片只能存放Integer.MAX_VALUE-128个docs

replica

可以理解为备份切片,相应的有primary shard(主分片)

主分片和备份片不会出现在同一个节点上(防止单点故障),默认情况下一个索引创建五个分片一个备份(即5primary+5replica=10个分片)

如果你只有一个节点,那么五个replica都无分配,此时cluster status会变成yellow

分片策略

分布式架构的透明隐藏属性,ElasticSearch是一个分别是架构,隐藏了复杂的处理机制,我们不用关心数据是按照什么机制分片的,最后放到哪个分片中

为了提升访问压力过大是单机无法处理所有请求的问题,Elasticsearch集群引入了副本策略replica。副本策略对index中的每个分片创建冗余的副本,处理查询时可以把这些副本当做主分片来对待(primary shard),此外副本策略提供了高可用和数据安全的保障,当分片所在的机器宕机,Elasticsearch可以使用其副本进行恢复,从而避免数据丢失。

集群发现机制

比如当我们启动了一个ES进程,启动了第二个时,这个进程就作为一个node自动发现了集群,并加入进去

Shard负载均衡:比如现在有10个shard,集群中有3个节点,es会均衡的进行分配,以保证每个节点均衡的负载请求,

请求路由:当索引一个文档的时候,文档会被存储到一个主分片中。 Elasticsearch 如何知道一个文档应该存放到哪个分片中呢?当我们创建文档时,它如何决定这个文档应当被存储在分片 1 还是分片 2 中呢?

首先这肯定不会是随机的,否则将来要获取文档的时候我们就不知道从何处寻找了。实际上,这个过程是根据下面这个公式决定的:

shard = hash(routing) % number_of_primary_shards

routing 是一个可变值,默认是文档的 _id ,也可以设置成一个自定义的值。 routing 通过 hash 函数生成一个数字,然后这个数字再除以 number_of_primary_shards (主分片的数量)后得到 余数 。这个分布在 0 到 number_of_primary_shards-1 之间的余数,就是我们所寻求的文档所在分片的位置。

扩容

垂直扩容:采购更强的机器

水平扩容

采购越来越多的普通服务器,性能比较一般,但是很多普通服务器组织在一起,就能构成强大的计算和存储能力
es一般采用方式二水平扩容的方式进行扩容。从成本上来说,内存容量小,并且性能相对较低的服务器相比较与内存容量大,性能好的服务器,在价格上的差距不是一个量级的。

从另一方面来说,elasticSearch是一套分布式的系统,分布式的存在也是为存放大量的数据。讲到elasticSearch的扩容,自然就会想到shard和replica shard。

elasticSearch拥有cluster discovery(集群发现机制),当我们启动一个新的节点,该节点会发现集群并且自动加入到集群中。并且es集群会自动进行各个shard之间的数据均衡处理。

并且当节减少时,es集群也会自动将减少的节点中的数据移到其他正在运行的节点中。

所以elasticSearch一般选择水平扩容的方式。

现在有6个shard,3个primary shard 3个replica shard,6个shard存放在6个服务器中,如何进行扩容扩容到9台服务器中?

因为primary shard在索引创建后就无法修改,所以需要将6台服务器扩容到9台服务器,只能对replica shard进行,可以修改索引配置,将replica shard的数量修改为2,此时replica shard的数量变为6个,加上3个primary shard就是9个

master节点:

  • 创建或删除索引
  • 增加或删除节点
  • 主节点的主要职责是和集群操作相关的内容,如创建或删除索引,跟踪哪些节点是集群的一部分,并决定哪些分片分配给相关的节点,稳定的主节点对集群的健康是非常重要的

节点对等

  • 创建或删除索引
  • 增加或删除索引
  • 每个节点都能接收请求,每个节点接收到请求后都能把该请求路由到有相关数据的其他节点上,接收原始请求的节点负责采集数据并返回给客户端

分片和副本机制

一个index中包含多个shard

每个shard都是一个最小的工作单元,承载部分数据,每个shard都是一个lucene实例,有完整的建立索引和处理请求的能力

增加节点时,shard会自动在nodes中均衡负载

每个document只会存在于某一个primary shard以及其对应的replica shard中,不可能存在于多个primary shard中

replica shard 是primary shard 的副本,负责容错,以及承担读请求的负载均衡,primary shard在创建索引的时候就固定了,relica shard的数量可以随时更改

primary shard 和 它对应的replica shard 不能放在同一台机器上,不然起不了容错的作用

index包含多个shard,每个shard都是一个最小工作单元,承载部分数据,lucene实例,完整的建立索引和处理请求的能力

Last modification:November 17, 2023
如果觉得我的文章对你有用,请随意赞赏