ElasticSearch分布式文档存储介绍

分布式文档存储

文档如何被路由到分片的

当你索引一个文档,他将会被索引到单独的分片,ElasticSearch是如何知道文档属于哪个分片的?

事实上,ElasticSearch是根据一个简单的算法实现的:

shard = hash(routing)%numOfPrimaryShards

routing是一个任意字符串,默认是_id,但也可以自定义。routing被hash后得到一个数字。这个数字除以主切片数得到一个余数,这个余数的范围将永远是0~(shards-1)的范围之间,这个余数,就是特定文档所在的分片。

这也解释了为什么主分片的数量只能在创建索引时定义且不能修改:如果主分片的数量在未来改变了,所有先前的路由值就失效了,文档也就永远找不到了。

主分片和复制分片如何交互

我们假设有三个节点的集群。它包含一个叫做 blogs 的索引并拥有两个主分片。每个主分片有两个复制分片。相同的分片不会放在同一个节点上,所以我们的集群是这样的:

我们能够发送请求给集群中任意一个节点。每个节点都有能力处理任意请求。每个节点都知道任意文档所在的节点,所以也可以将请求转发到需要的节点。下面的例子中,我们将发送所有请求给 Node 1 ,这个节点我们将会称之为请求节点(requesting node)。当我们发送请求,最好的做法是循环通过所有节点请求,这样可以平衡负载。

针对新建、索引和删除文档,请求步骤如下图:

注:新建、索引和删除请求都是 写(write)操作,写(write)操作必须在主分片上成功完成才能复制到相关的复制分片上。

下面我们罗列在主分片和复制分片上成功新建、索引或删除一个文档必要的顺序步骤:

1. 客户端给 Node 1 发送新建、索引或删除请求。

2. 节点使用文档的 _id 确定文档属于分片 0 。它转发请求到 Node 3 ,分片 0 位于这个节点上。

3. Node 3 在主分片上执行请求,如果成功,它转发请求到相应的位于 Node 1 和 Node 2 的复制节点上。当所有的复制节点报告成功, Node 3 报告成功到请求的节点,请求的节点再报告给客户端。

客户端接收到成功响应的时候,文档的修改已经被应用于主分片和所有的复制分片。你的修改生效了。

有很多可选的请求参数允许你更改这一过程。你可能想牺牲一些安全来提高性能。这一选项很少使用因为Elasticsearch已经足够快。

<1>replication

复制默认的值是 sync 。这将导致主分片得到复制分片的成功响应后才返回。

如果你设置 replication 为 async ,请求在主分片上被执行后就会返回给客户端。它依旧会转发请求给复制节点,但你将不知道复制节点成功与否。

<2>consistency

默认主分片在尝试写入时需要 规定数量或过半的分片(可以是主分片或复制分片)可用。这是防止数据被写入到错的网络分区。规定的数量计算公式如下:

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

primary:主分片数,

number_of_replicas:在索引中设置的复制分片数(不是现在活动的复制分片的数)

consistency 允许的值为 one (只有一个主分片), all (所有主分片和复制分片)或者默认的 quorum 或过半分片。

注意 number_of_replicas 是在索引中的的设置,用来定义复制分片的数量,而不是现在活动的复制节点的数量。如果你定义了索引有3个复制分片,那规定数量是:

int( (primary + 3 replicas) / 2 ) + 1 = 3

如果在主分片尝试写入时,可用的分片数小于3,则不能创建、索引或删除任何文档。

<3>timeout

当复制分片不足时,ElasticSearch会等待更多的分片出现,默认等待一分钟,如果需要,可以设置timeout参数,让他终止的更早,100 表示100毫秒,100s表示100秒。

检索文档

上边说了,文档的创建,删除,索引必须在主分片上进行,但文档能够从主分片或任意一个复制分片被检索。

下面我们罗列在主分片或复制分片上检索一个文档必要的顺序步骤:

1. 客户端给 Node 1 发送get请求。

2. 节点使用文档的 _id 确定文档属于分片 0 。分片 0 对应的复制分片在三个节点上都有。此时,它转发请求到 Node 2 。

3. Node 2 返回endangered给 Node 1 然后返回给客户端。

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

局部更新文档

update API 结合了之前提到的读和写的模式。

下面我们罗列执行局部更新必要的顺序步骤:

1. 客户端给 Node 1 发送更新请求。

2. 它转发请求到主分片所在节点 Node 3 。

3. Node 3 从主分片检索出文档,修改 _source 字段的JSON,然后在主分片上重建索引。如果有其他进程修改了文档,它以 retry_on_conflict 设置的次数重复步骤3,都未成功则放弃。

4. 如果 Node 3 成功更新文档,它同时转发文档的新版本到 Node 1 和 Node 2 上的复制节点以重建索引。当所有复制节点报告成功, Node 3 返回成功给请求节点,然后返回给客户端。

注:文档更新成功后,切片转发的是整个文档的新版本,而非更新请求。

多文档更新

mget 和 bulk API与单独的文档类似。差别是请求节点知道每个文档所在的分片。它把多文档请求拆成 每个分片的对文档请求,然后转发每个参与的节点。

一旦接收到每个节点的应答,然后整理这些响应组合为一个单独的响应,最后返回给客户端。

下面我们罗列通过一个 mget 请求检索多个文档的顺序步骤:

1. 客户端向 Node 1 发送 mget 请求。

2. Node 1 为每个分片构建一个多条数据检索请求,然后转发到这些请求所需的主分片或复制分片上。当所有回复被接收, Node 1 构建响应并返回给客户端。

routing 参数可以被 docs 中的每个文档设置。

下面我们罗列使用一个 bulk 执行多个 create 、 index 、 delete 和 update 请求的顺序步骤:

1. 客户端向 Node 1 发送 bulk 请求。

2. Node 1 为每个分片构建批量请求,然后转发到这些请求所需的主分片上。

3. 主分片一个接一个的按序执行操作。当一个操作执行完,主分片转发新文档(或者删除部分)给对应的复制节点,然后执行下一个操作。复制节点为报告所有操作完成,节点报告给请求节点,请求节点整理响应并返回给客户端。

--------------------------------------------------------------------------------------------------------------------

搜索

空搜索

最基本的搜索API表单是 空搜索(empty search),它没有指定任何的查询条件,只返回集群索引中的所有文档。

hits

响应中最重要的部分是 hits ,它包含了 total 字段来表示匹配到的文档总数, hits 数组还包含了匹配到的前10条数据。

hits 数组中的每个结果都包含 _index 、 _type 和文档的 _id 字段,被加入到 _source 字段中这意味着在搜索结果中我们将可以直接使用全部文档。这不像其他搜索引擎只返回文档ID,需要你单独去获取文档。

每个节点都有一个 _score 字段,这是 相关性得分(relevance score),它衡量了文档与查询的匹配程度。默认的,返回的结果中关联性最大的文档排在首位;这意味着,它是按照 _score 降序排列的。这种情况下,我们没有指定任何查询,所以所有文档的相关性是一样的,因此所有结果的 _score 都是取得一个中间值 1。max_score 指的是所有文档匹配查询中 _score 的最大值。

took

took 告诉我们整个搜索请求花费的毫秒数。

shards

_shards告诉我们参与查询的分片数( total 字段),有多少是成功的( successful 字段),有多少的是

失败的( failed 字段)。通常我们不希望分片失败,不过这个有可能发生。如果我们遭受一些重大的故障导致主分片和复制分片都故障,那这个分片的数据将无法响应给搜索请求。这种情况下,Elasticsearch将报告分片 failed ,但仍将继续返回剩余分片上的结果。

timeout

time_out 值告诉我们查询超时与否。一般的,搜索请求不会超时。如果响应速度比完整的结果更重要,你可以定义 timeout 参数为 10 或者 10ms (10毫秒),或者 1s (1秒)

此时ElasticSearch返回的结果是截止到超时前所搜集的结果;使用超时是因为对于业务需求来说非常重要,而不是因为你想中断执行长时间运行的查询。

注:timeout为true不会停止执行查询,它只是告诉你目前顺利返回的结果并关闭了连接。尽管请求已经结束了,但在后台其他的分片可能还在执行查询。

猜你喜欢

转载自blog.csdn.net/zhtzh312/article/details/88863077
今日推荐