首页
Linux教程
Linux实战教程
Shell教程
Mysql教程
Keepalived教程
Linux基础教程
Linux进阶教程
运维题库
运维干货
视频教程
运维资讯
资源下载
关于我们
首页 ElasticSearch底层文档解析

底层文档解析

1.4 .文档的底层操作原理解析

1.文档的写流程

新建,删除,更新操作我们都可以归纳为写(write)操作,它们必须在主分片上成功完成才能复制到相关的复制分片上。

如下图所示,下面是我们罗列的主分片和副本分片上成功新建,删除,更新一个文档必要的顺序步骤:

  1. 客户端可以请求任意集群节点(比如”es01″),此时我们称该节点为”协调节点(coordinating)”;
  2. 协调节点计算数据的存储路由,默认会根据文档的”_id”来计算,假设计算结果确定文档属于分片0,它转发请求到”es03″,分片0位于这个节点上;
  3. “es03″节点在主分片上执行写请求将数据进行保存;
  4. 主分片数据保存成功后,它会转发请求到相应副本分片节点,如下图所示,副本分片位于”es01″节点上;
  5. 当所有的副本分片节点保存数据成功后,会告知”es03″节点写请求执行成功;
  6. “es03″节点(主分片节点)在反馈给客户端写请求操作的执行结果;
  7. 客户端接收到成功响应的时候,文档的修改已经应用于主分片和所有的副本分片,你的修改生效了。

综上所述,文档的写操作,主分片和副本分片拥有强一致性,即主分片和副本分片的数据是一致的。

温馨提示:

  1. 我们可以通过修改consistency参数的值来改变上述写入的流程,其值为one,all和quorum(默认值)。

    one:

    • 只要主分片状态写入成功,就认为数据写入成功,直接返回给客户端,并不等待任意的副本分片同步数据。

    all:

    • 必须要主分片和所有的副本分片数据写入成功后才允许执行写操作。

    quorum:

    • 只要主分片和大部分副本分片(计算公式为: “int((primary + number_of_replicas)/2) + 1”)写入成功就返回给客户端,并不需要等待所有的副本节点同步数据。这是默认的策略。生产环境中我建议大家就是用默认的策略即可。
  2. 如果没有足够的副本分片写入,ES会等待,希望更多的分片出现。默认情况下等待的超时时间为1分钟,如果你需要,可以使用timeout参数使它更早终止,比如修改为: 5s, 10s, 30s等。

2.文档的读流程-单个文档搜索

文档能够从主分片或者任意一个副本分片被检索。

如下图所示,我们罗列在主分片或者复制分片上检索一个文档必要的顺序步骤:

  1. 客户端给协调节点(“es03”)发送get请求;
  2. 协调节点默认使用文档的”_id”确定文档属于分片”0″,分片”0″对应的副本分片在”es01″和”es03″节点上都有,此时,它转发请求到”es01″;
  3. “es01″返回文档(document)给”es03″,然后由”es03″返回给客户端;

对于读请求,为了平衡负载均衡,请求节点会为每个请求选择不同的分片,它会循环所有的分片副本。

可能的情况是,一个被索引的文档已经存在于主分片上却还没来得及同步到副本分片上。

这时副本分片会报告文档未找到,主分片会成功返回文档。一旦索引请求成功返回给用户,文档则在主分片和副本分片都是可用的。

我猜测有可能你会问:

  1. 为啥”es03″节点不直接返回文档给客户端呢?
  2. 当”es01″节点查询到数据后为啥不直接返回给客户端而是要将数据交给”es03″节点呢?

参考答案:

  1. 当”es03″节点负载比较高时,如果把文档的搜索工作还交给当前节点,无疑是雪上加霜,因为他消耗的不仅仅是CPU,内存,套接字等资源,而将任务交给”es01″节点后,就无需为本次搜索承担额外的资源了,换句话说,就会减少本次查询对系统资源负载的消耗;
  2. 当”es01″节点查询到数据后,并不会直接将数据返回给客户端,我猜想原因之一是不知道客户端的IP地址,原因之二就是如果知道了IP地址也得需要建立TCP连接才能完成传输,与其这样,还不如直接交由已经建立TCP连接的”es03″节点进行数据的返回;

3.文档的读流程-全文搜索

对于全文搜索而言,文档可能分散在各个节点上,那么在分布式的情况下,分为两个阶段,即搜索(query)和取回(fetch)这两个阶段。

搜索(query)阶段包含以下三步:

  1. 客户端发送一个search(搜索)请求给”es03″,”es03″创建了一个长度为”from + size”(这两个参数大家并不陌生,在分页查询中我们有使用到)的空优先级队列;
  2. “es03″转发这个搜索请求中每个分片的主分片或者副本分片,每个分片在本地执行这个查询并将结果存储到一个大小为”from + size”的有序本地优先级队列里去;
  3. 每个分片返回文档(document)的ID和它优先级队列里的所有document的排序值给协调节点”es03″,”es03″把这些值合并到自己的优先队列里产生全局排序结果;

取回(fetch)阶段包含以下三步:

  1. 协调节点辨别出哪个文档(document)需要取回,并且向相关分片发出GET请求;
  2. 每个分片加载document并且根据需要丰富(enrich)它们(因为query阶段拿到的是排序后的”_id”,并没有真正拿到数据),然后再将document返回协调节点;
  3. 一旦所有的document都被取回,协调节点会将结果返回给客户端;

4.文档的更新流程

部分更新一个文档结合了先前说明的读取和写入流程。

部分更新一个文档的步骤如下:

  1. 客户单向协调节点(“es03”)发送更新请求;
  2. 协调节点通过计算,发现更新请求的主分片在”es02″上,因此将请求转发到主分片所在的”es02″;
  3. “es02″从主分片检索文档,修改”_source”字段中的JSON,并且尝试重新索引主分片的文档。如果文档已经被另一个进程修改(该文档底层对应的文件就会被上”锁”),它会重试步骤3,超过retry_on_conflict次后放弃;
  4. 如果”es02″成功更新文档,它将新版本的文档并行转发到其它的副本分片,重新建立索引;
  5. 一旦所有副本分片都返回成功,”es02″向协调节点也返回成功,协调节点向客户端返回成功;

温馨提示:

  1. 当主分片把更改转发到副本分片时,它不会转发更新请求。相反,它转发完整文档的新版本。
  2. 请记住,这些更改将会异步转发到副本分片,并且不能保证他们以发送他们相同的顺序到达。如果elasticsearch仅转发更改请求,则可能以错误的顺序应用更改,导致得到损坏的文档。

5.多文档的批量操作流程

mget和bulk API的模式类似于单文档模式。

区别在于协调节点知道每个文档存在于哪个分片中。它将整个文档请求分解成每个分片的多文档请求,并且将这些请求并行转发到每个参与节点。

协调节点一旦收到来自节点的应答,就将每个节点的响应收集整理成单个响应,返回给客户端。

本文链接:https://www.yunweibase.com/archives/257

上一篇:

ElasticSearch介绍

网友评论comments

发表评论

邮箱地址不会被公开。 必填项已用*标注

暂无评论

Copyright © 运维基地 保留所有权
扫二维码
扫二维码
返回顶部