二、基础入门
4. 分布式文档存储
首先再次确认几个概念
-
索引:ElasticSearch 中的索引对应 MySQL 中的 Database ,也就说 ElasticSearch 中的索引更像是一种数据存储集合,即用于存储文档。
-
需要注意!ES 种的索引,是一种存储数据的集合,是一个数据库
,和传统意义的索引不同 -
Type(类型):类型更像是一张表,但是在6版本之后废除了
-
分片:属于逻辑上的含义,数据存放在分片上,分片分布在不同的机器上,主要用于荣灾和提升查询性能
-
节点:一个运行的es 的实例
- master 节点:负责管理集群范畴的变更,创建、删除索引,创建、删除节点
- client 节点
-
集群:一堆具有相同节点名称的节点
4.1. 路由一个文档到一个分片中
- 寻找文档被存储在哪个分片中
shard = hash(routing) % number_of_primary_shards
routing
是一个可变值,默认是文档的 _id
- 根据此可以确定在第几个主分片,所以索引在创建的时候,就需要确定主分片的数量,并且不能改变
4.2. 主分片和副本分片如何交互
-
我们可以发送请求到集群中的任一节点。 每个节点都有能力处理任意请求。
-
每个节点都知道集群中任一文档位置,所以可以直接将请求转发到需要的节点上。
-
在下面的例子中,将所有的请求发送到
Node 1
,我们将其称为 协调节点(coordinating node) 。
4.3. 新建、索引和删除文档
- 新建、索引和删除 请求都是 写 操作, 必须在主分片上面完成之后才能被复制到相关的副本分片,
- 客户端向
Node 1
发送新建、索引或者删除请求。 - 节点使用文档的
_id
确定文档属于分片 0 。请求会被转发到Node 3
,因为分片 0 的主分片目前被分配在Node 3
上。 Node 3
在主分片上面执行请求。如果成功了,它将请求并行转发到Node 1
和Node 2
的副本分片上。一旦所有的副本分片都报告成功,Node 3
将向协调节点报告成功,协调节点向客户端报告成功。
- 在客户端收到成功响应时,文档变更已经在主分片和所有副本分片执行完成,变更是安全的。
- 这里可以设置写入的协议是 quorum 或者是 all 协议
4.4. 取回一个文档
1、客户端向 Node 1
发送获取请求。
2、节点使用文档的 _id
来确定文档属于分片 0
。分片 0
的副本分片存在于所有的三个节点上。 在这种情况下,它将请求转发到 Node 2
。
3、Node 2
将文档返回给 Node 1
,然后将文档返回给客户端。
- 在处理读取请求时,协调结点在每次请求的时候都会通过轮询所有的副本分片来达到负载均衡。
- 可能存在延迟原因,形成粘读
4.5. 局部更新文档
- 客户端向
Node 1
发送更新请求。 - 它将请求转发到主分片所在的
Node 3
。 Node 3
从主分片检索文档,修改_source
字段中的 JSON ,并且尝试重新索引主分片的文档。 如果文档已经被另一个进程修改,它会重试步骤 3 ,超过retry_on_conflict
次后放弃。- 如果
Node 3
成功地更新文档,它将新版本的文档并行转发到Node 1
和Node 2
上的副本分片,重新建立索引。 一旦所有副本分片都返回成功,Node 3
向协调节点也返回成功,协调节点向客户端返回成功。
5. 搜索---最基本的工具
-
到此,我们可以实现将 文档进行简单的存储,然后根据 ID 进行检索,
-
Elasticsearch 不只会
_存储(stores)_
文档,为了能被搜索到也会为文档添加_索引(indexes)_
,这也是为什么我们使用结构化的 JSON 文档
,而不是无结构的二进制数据。 -
文档中的每个字段都将被索引并且可以被查询
5.1. 空搜索
搜索API的最基础的形式是没有指定任何查询的空搜索,它简单地返回集群中所有索引下的所有文档:
GET /_search
返回的结果(为了界面简洁编辑过的)像这样:
{
"hits" : {
"total" : 14,
"hits" : [
{
"_index": "us",
"_type": "tweet",
"_id": "7",
"_score": 1,
"_source": {
"date": "2014-09-17",
"name": "John Smith",
"tweet": "The Query DSL is really powerful and flexible",
"user_id": 2
}
},
... 9 RESULTS REMOVED ...
],
"max_score" : 1
},
"took" : 4,
"_shards" : {
"failed" : 0,
"successful" : 10,
"total" : 10
},
"timed_out" : false
}
5.1.1. hits
返回结果中最重要的部分是 hits
,它包含 total
字段来表示匹配到的文档总数,并且一个 hits
数组包含所查询结果的前十个文档。
5.1.2. took
took
值告诉我们执行整个搜索请求耗费了多少毫秒。
5.1.3. shards
_shards
部分告诉我们在查询中参与分片的总数,以及这些分片成功了多少个失败了多少个。
5.1.4. timeout
timed_out
值告诉我们查询是否超时。默认情况下,搜索请求不会超时。如果低响应时间比完成结果更重要,你可以指定 timeout
为 10 或者 10ms(10毫秒),或者 1s(1秒):
GET /_search?timeout=10ms
- 在请求超时之前,Elasticsearch 将会返回已经成功从每个分片获取的结果。
5.2. 多索引,多类型
-
在一个或多个特殊的索引并且在一个或者多个特殊的类型中进行搜索。我们可以通过在URL中指定特殊的索引和类型达到这种效果
-
/_search
- 在所有的索引中搜索所有的类型
-
/gb/_search
- 在
gb
索引中搜索所有的类型
- 在
-
/gb,us/_search
- 在
gb
和us
索引中搜索所有的文档
- 在
-
/g*,u*/_search
- 在任何以
g
或者u
开头的索引中搜索所有的类型
- 在任何以
-
/gb/user/_search
- 在
gb
索引中搜索user
类型
- 在
-
/gb,us/user,tweet/_search
- 在
gb
和us
索引中搜索user
和tweet
类型
- 在
-
/_all/user,tweet/_search
- 在所有的索引中搜索
user
和tweet
类型
- 在所有的索引中搜索
5.3. 分页
如果每页展示 5 条结果,可以用下面方式请求得到 1 到 3 页的结果:
GET /_search?size=5
GET /_search?size=5&from=5
GET /_search?size=5&from=10