elasticsearch 增删改查底层原理

elasticsearch专栏:https://www.cnblogs.com/hello-shf/category/1550315.htmlhtml

1、预备知识

在对document的curd进行深度分析以前,咱们不得不了解如下几个小的知识点,不了解一下几个知识点咱们将很难理解document是如何进行增删改查的。node

 

1.一、路由(索引)与primary shard不可变

你们有没有考虑过这个问题,当你索引一个文档,它被存储在单独一个主分片上。Elasticsearch是如何知道文档属于哪一个分片的呢?当你建立一个新文档,它是如何知道是应该存储在分片1仍是分片2上的呢? 进程不能是随机的,由于咱们未来要检索文档。事实上,它根据一个简单的算法决定:算法

shard = hash(routing) % number_of_primary_shards 

routing值是一个任意字符串,它默认是 _id 但也能够自定义。这个 routing 字符串经过哈 希函数生成一个数字,而后除以主切片的数量获得一个余数(remainder),余数的范围永远 是 0 到 number_of_primary_shards - 1 ,这个数字就是特定文档所在的分片。负载均衡

这也解释了为何主分片的数量只能在建立索引时定义且不能修改:若是主分片的数量在将来改变了,全部先前的路由值就失效了,文档也就永远找不到了。async

咱们演示一下这个路由的过程。假设咱们有三个节点,一个student索引,对应有三个primary shard和一个replica shard。此时集群如图1所示elasticsearch

向该节点中插入一个document,而且咱们指定_id(在es中_id能够自定义es也能够自动生成)假如_id = 1000,根据咱们上面描述,此时会按照以下算法计算其会命中哪一个shard。假设此时hash(1000)= 13;函数

shard = hash(routing) % number_of_primary_shards
即:
shard = 13 % 3 = 1;(假设hash(1000) = 13)
注:由于es的hash函数具体是怎么计算的不得而知,也不重要,咱们主要是关注其原理。

 根据计算可得该插入请求会命中P1,shard此时会将该document插入到P1。是否是很简单。性能

以上也可就是es路由的过程,也可称为es索引(这个索引是动词,理解一下)过程。spa

 

1.二、shard负载均衡与节点对等

在es集群中每一个节点,每一个shard(包括primary shard和replica shard)都具有处理任何请求的能力。这意味着在es集群中节点间是高度的负载均衡的,即并非只有主节点是流量的入口,每一个节点都具有处理请求的能力。primary shard和replica shard也是高度负载均衡的,由于并非只有primary shard才具有处理curd的能力,replica shard可处理检索的请求。这也是es的性能为何表现这么好的缘由之一。code

 

2、document增、删、改

2.一、增删改过程分析

新建、索引和删除请求都是写(write)操做,它们必须在primary shard上成功完成才能复制到相关的replica shard分片上。

关于新增document索引过程能够参考《es的索引过程》

 

 

 

 如上图所示,从客户端发起请求到es集群向客户端响应大体能够分为以上6个阶段。

阶段1:

  客户端向node1发起增、删、改请请求。node1将做为协调节点(coordinate node)进行相关工做。

阶段2:

  node1根据文档 _id 计算出命中的primary shard为P1,而后将请求转发到node2,P1分片位于node2上面。

阶段3:

  node2在P1上处理该请求。若是请求处理成功,node2将会把请求继续转发到其副本R1上。R1位于node3。

阶段4:

  node3在R1上处理完该请求,若是成功,node3会将处理成功的消息返回给node2。

阶段5:

  node2收到P1副本处理成功的消息,也就意味着该请求已经处理完成。而后将处理结果返回给node1节点。

阶段6:

  协调节点node1收到响应结果后,将该结果返回给客户端。

整个过程就完成了。

看到这里你们是否是也在思考一个请求进来,我还要等待全部的分片都处理完成这个操做才算是完成,这样是否是很影响响应速度。基于这个思考,es一样也给咱们提供了自定义参数的支持,好比咱们可使用replication参数来指定primary shard是否是要等到replica shard处理完成后才能响应到客户端。可是,该配置配置参数并不推荐使用,你们知道有这么个东西就好了。

replication:默认值为  sync  该值意味着primary shard须要等到其全部的副本分片都完成后才会响应客户端。若是咱们将该值设置为  async ,意味着primary shard完成后就会返回给客户端,可是并不意味着其不会将请求转发到副本上,主分片依然会将请求转发到replica shard上,只不过咱们再也不肯定副本是否是也完成了该请求,这样将不能保证数据的一致性。
 

2.一、写一致性保障

首先须要说明的一点,增删改其实都是一个写操做,因此这里的写指的是增删改三个操做。
这里咱们所说的写一致性指的是primary shard和replica shard上数据的一致性。es API为咱们提供了一个可自定的参数consistency。该参数可让咱们自定义处理一次增删改请求,是否是必需要求全部分片都是active的才会执行。
该参数可选的值有三个:one,all,quorum(default,默认)。
1 one:要求咱们这个写操做,只要有一个primary shard是active活跃可用的,就能够执行。
2 all:要求咱们这个写操做,必须全部的primary shard和replica shard都是活跃的,才能够执行这个写操做
3 quorum:默认的值,要求全部的shard中,必须是大部分的shard都是活跃的,可用的,才能够执行这个写操做

 上面三点其实很好理解,只有quorum所谓的“大部分”感受不是那么的明确。下面有个公式,当集群中的active(可用)分片数量达到以下公式结果时写操做就是能够执行的。不然该操做将没法进行。

int( (primary + number_of_replicas) / 2 ) + 1

依然用咱们上面的例子,假设咱们建立了一个student索引,而且设置primary shard为3个,replica shard有1个(这个1个是相对于索引来讲的,对于主分片该数字1意味着每一个primary shard都对应的存在一个副本)。也就意味着primary=3,number_of_replicas=1(依然是相对于索引)。shard总数为6。

此时计算上面公式可知:

int((3+1)/2) + 1 = 3
也就是说当集群中可用的shard数量>=3写操做就是能够执行的。
说了这么多好像还没解释以上跟写一致性有什么关系。es对写一致性的保证就是经过quorum来保证的,觉得quorum要求es集群中的可用shard数量达到必定要求才能执行。也就间接保证了shard的数据一致性。
具体使用也很简单
PUT /index/type/id?consistency=quorum

 固然若是咱们不指定就是使用默认的,也就是quorum。

 

3、document检索

document的检索过程和增删改略有不一样:文档可以从主分片(primary shard)或任意一个复制分片(replicashard)被检索。

 

检索过程大体能够分为4个阶段

阶段1:

  客户端向node1发送检索请求。node1将做为协调节点(coordinate node)进行相关工做。

阶段2:

  node1根据文档 _id 计算出命中的primary shard为P1,node1会找到P1的全部副本,而后经过round-robin随机轮询算法,在primary shard以及其全部replica中随机选择一个,让读请求负载均衡。假如此时随机选取的是P1,node1会将该请求转发到P1对应的节点上。

阶段3:

  P1处理完该请求将结果返回给协调节点node1。

阶段4:

  协调节点node1收到该node2的相应结果,进而将该结果返回给客户端。

可能的状况是,一个被索引的文档已经存在于主分片上却还没来得及同步到复制分片上。这时复制分片会报告文档未找到,主分片会成功返回文档。一旦索引请求成功返回给用户,文档则在主分片和复制分片都是可用的。
对与mget和bulk批量请求,与单文档检索还有一点区别,差异是协调节点须要计算每一个文档所在的分片。它把多文档请求拆成每一个分片的对文档请求,而后转发每一个参与的节点。一旦接收到每一个节点的应答,而后整理这些响应组合为一个单独的响应,最后返回给客户端。
 
 
 
 

 

  参考文献:

  《elasticsearch-权威指南》

 

  若有错误的地方还请留言指正。

  原创不易,转载请注明原文地址:http://www.javashuo.com/article/p-qdjxjksb-cn.html

相关文章
相关标签/搜索