将文档路由到从库中
分片 = hash(routing) % 主分片数量
routing 值可以是任何的字符串, 默认是文档的 _id ,但也可以设置成一个自定义的值。 routing 字符串被传递到一个哈希函数以生成一个数字,然后除以索引的主分片的数量 得到 余数 remainder. 余数将总是在 0 到 主分片数量 - 1 之间, 它告诉了我们用以存放 一个特定 文档的分片编号。
解释了为什么主分片的数量只能在索引创建时设置、而且不能修改。 如果主分片的数量一旦在日后进行了修改,所有之前的路由值都会无效,文档再也无法被找到。
所有文档 APIs ( get , index , delete , bulk , update 和 mget ) 都可以接受 routing 参数
主从库之间是如何通信的
为了便于说明,假设我们有由3个节点的集群。 它 包含一个名为blogs的索引,它有两个主分片。 每个主要分片都有 两个副本。 永远不会将同一分片的副本分配给同一节点,因此我们的群集也是如此 看起来像<>。
[[img-distrib]] .A cluster with three nodes and one index image::images/04-01_index.png["Acluster with three nodes and one index"]
我们可以将请求发送到集群中的任何节点。 每个节点都完全有能力服务任何要求。 每个节点都知道集群中每个文档的位置,因此也可以将请求直接转发到所需节点。 在下面的例子中,我们将发送所有的对节点1的请求,我们将其称为请求节点。
提示:发送请求时,最好通过循环遍历所有节点集群,以分散负载。
创建,索引和删除请求是写操作,必须成功
下面我们列出了成功创建,索引或删除a所需的步骤顺序 主要和任何副本分片上的文档,如<>中所述:
- 客户端向Node_1发送创建,索引或删除请求。
- 节点使用文档的_id来确定文档属于分片 0。它将请求转发到节点3,其中当前是碎片0的主副本 分配。
- 节点3在主分片上执行请求。如果成功,它会转发 并行请求节点1和节点2上的副本分片。一旦所有的复制品 分片报告成功,节点3向报告的请求节点报告成功 对客户的成功。
注意:
- 复制的默认值是sync。 这会导致主分片等待在返回之前来自副本分片的成功响应。
- 如果将复制设置为异步,则会立即将成功返回给客户端
- 请求已在主分片上执行。 它仍然会将请求转发给复制品,但你不知道复制品是否成功。
- 建议使用默认的同步复制,因为可以重载Elasticsearch通过发送太多请求而不等待他们的
默认情况下,主分片需要法定数量或大多数分片副本(分片所在的位置)复制可以是主要或副本碎片)甚至在尝试写入之前可用操作。这是为了防止将数据写入网络分区的“错误一侧”。一个 仲裁定义为:
int( (primary + number_of_replicas) / 2 ) + 1
允许的一致性值是一个(只是主要分片),所有(主要的)和所有副本)或默认仲裁或大多数碎片副本。请注意,number_of_replicas是索引设置中指定的副本数,不是当前活动的副本数量。如果您指定了索引应该有3个副本,然后是法定人数:
int( (primary + 3 replicas) / 2 ) + 1 = 3
默认情况下,新索引具有1个分片,这意味着应该有两个活动分片副本为了满足法定人数的需要而需要。 但是,这些默认设置会阻止我们对单节点集群做任何有用的事情。 为了避免这个问题,要求
a quorum is only enforced when number_of_replicas is greater than 1 .
仅当number_of_replicas大于1时才会强制执行仲裁
获取一个文档
下面我们列出从主服务器或副本服务器检索文档的步骤顺序 碎片,如<>所示:
- 客户端向节点1发送get请求。
- 节点使用文档的_id来确定文档属于分片0。所有三个节点上都存在shard 0的副本。在这个场合,它转发了请求节点2。
- 节点2将文档返回到节点1,节点1将文档返回给客户端。
对于读取请求,请求节点将在每个请求上选择不同的分片副本为了平衡负载 - 它循环遍历所有碎片副本。
文档可能已在主分片上编入索引但尚未编入索引复制到副本分片。在这种情况下,副本可能会报告文档没有存在,而主要成功返回文档。
更新文档中的一部分
下面我们列出用于对文档执行部分更新的步骤序列,如 在<>中描述:
1.客户端向Node_1发送更新请求。
2.它将请求转发到节点3,在节点3中分配主分片。
3.节点3从主分片中检索文档,更改中的JSON_source字段,并尝试在主分片上重新索引文档。如果是文件已被另一个进程更改,它重试第3步放弃之前retry_on_conflict次。
4.如果节点3已成功更新文档,则转发新文档与节点1和节点2上的副本分片并行的文档版本重建索引。一旦所有副本分片报告成功,节点3就会报告成功请求节点,向客户端报告成功。更新API还接受路由,复制,一致性和超时 <>中解释的参数
NOTE
当主分片将更改转发到其副本分片时,它不会转发更新请求。 相反,它转发整个文档的新版本。 请记住这些更改将异步转发到副本分片,并且无法保证他们将按照他们发送的顺序到达。 如果Elasticsearch只转发了更改,可能会以错误的顺序应用更改,从而导致损坏文献。
多文档模式
mget和批量API的模式与单个文档的模式类似。不同之处在于请求节点知道每个文档在哪个分片中存在。它将多文档请求分解为每个分片的多文档请求,以及将这些并行转发到每个参与节点。
一旦它从每个节点接收到答案,它就会将他们的响应整理成一个响应,它返回给客户端。
[[img-distrib-mget]] .Retrieving multiple documents with mget image::images/04- 05_mget.png["Retrieving multiple documents with mget"]
下面我们列出了使用单个文档检索多个文档所需的步骤顺序
mget请求,如<>所示:
1.客户端向Node_1发送mget请求。
2.节点1为每个分片构建一个多重获取请求,并将这些请求并行转发托管每个所需主要或副本分片的节点。一旦所有回复都是收到后,节点1构建响应并将其返回给客户端。可以为docs数组中的每个文档和首选项设置路由参数可以为顶级mget请求设置参数。
下面我们列出执行多个create,index所需的步骤序列,
在单个批量请求中删除和更新请求,如<>中所述:
1.客户端向Node_1发送批量请求。
2.节点1为每个分片构建一个批量请求,并将这些请求并行转发给托管每个节点的节点都涉及主分片。
3.主分片一个接一个地连续执行每个动作。作为每个动作成功后,主要将新文档(或删除)转发到其副本分片中并行,然后继续下一个动作。一旦所有副本分片报告所有人都成功动作,节点向请求节点报告成功,该节点整理响应并将它们返回给客户端。批量API还接受顶级的复制和一致性参数
对于整个批量请求,以及每个请求的元数据中的路由参数。
Why the funny format?
当我们在<>之前了解批量请求时,您可能会问自己:为什么批量API是否需要带有换行符的有趣格式,而不仅仅是发送包含在JSON数组中的请求,比如mget` API?''
要回答这个问题,我们需要解释一下背景:
批量请求中引用的每个文档可以属于不同的主分片,其中的一部分可以分配给集群中的任何节点。这意味着每一个动作,批量请求内部需要转发到正确节点上的正确分片。如果单个请求被包装在JSON数组中,那就意味着我们会这样做
需要:
- 将JSON解析为数组(包括文档数据,可能非常大)
- 查看每个请求以确定它应该去哪个分片
- 为每个分片创建一组请求
- 将这些数组序列化为内部传输格式
- 将请求发送到每个分片
它可以工作,但需要大量的RAM来保存基本相同数据的副本,并且会创建更多的数据结构,JVM必须花费时间垃圾 收集。
相反,Elasticsearch会进入原始请求所在的网络缓冲区已收到并直接读取数据。它使用换行符来识别和只解析小动作/元数据行,以决定哪个分片应该处理每个分片请求。
这些原始请求将直接转发到正确的分片。没有多余的复制数据,没有浪费的数据结构。整个请求过程在中处理最小的内存量。
搜索
- 类似于 年龄 、 性别 、 加入日期 等结构化数据,类似于在SQL中进行查询。
- 全文搜索,查找整个文档中匹配关键字的内容,并根据相关性
- 或者结合两者。
虽然很多搜索操作是安装好Elasticsearch就可以用的,但是想发挥它的潜力,你需要明白以 下内容:
名字 | 说明 |
映射 (Mapping) | 每个字段中的数据如何被解释 |
统计 (Analysis) | 可搜索的全文是如何被处理的 |
查询 (Query DSL) | Elasticsearch使用的灵活强的查询语言 |