Elasticsearch架构原理

1、Elasticsearch的节点类型

1.1 Master节点

在Elasticsearch启动时,会选举出来一个Master节点。当某个节点启动后,然后

使用Zen Discovery机制找到集群中的其他节点,并建立连接。

discovery.seed_hosts: ["192.168.21.130", "192.168.21.131", "192.168.21.132"]

并从候选主节点中选举出一个主节点。

cluster.initial_master_nodes: ["node1", "node2","node3"]

Master节点主要负责:

管理索引(创建索引、删除索引)、分配分片

维护元数据

管理集群节点状态

不负责数据写入和查询,比较轻量级

一个Elasticsearch集群中,只有一个Master节点。在生产环境中,内存可以相对

小一点,但机器要稳定。

1.2 DataNode节点

在Elasticsearch集群中,会有N个DataNode节点。DataNode节点主要负责:

数据写入、数据检索,大部分Elasticsearch的压力都在DataNode节点上

在生产环境中,内存最好配置大一些

二 、分片和副本机制

2.1 分片(Shard)

Elasticsearch是一个分布式的搜索引擎,索引的数据也是分成若干部分,分布在不同的服务器节点中

分布在不同服务器节点中的索引数据,就是分片(Shard)。Elasticsearch会自动

管理分片,如果发现分片分布不均衡,就会自动迁移

一个索引(index)由多个shard(分片)组成,而分片是分布在不同的服务器上的

2.2 副本

为了对Elasticsearch的分片进行容错,假设某个节点不可用,会导致整个索引库

都将不可用。所以,需要对分片进行副本容错。每一个分片都会有对应的副本。

在Elasticsearch中,默认创建的索引为1个分片、每个分片有1个主分片和1个副本

分片。

每个分片都会有一个Primary Shard(主分片),也会有若干个Replica Shard(副

本分片)

Primary Shard和Replica Shard不在同一个节点上

2.3 指定分片、副本数量

bash 复制代码
// 创建指定分片数量、副本数量的索引
2 PUT /job_idx_shard_temp
3 {
4 "mappings":{
5 "properties":{
6 "id":{"type":"long","store":true},
7 "area":{"type":"keyword","store":true},
8 "exp":{"type":"keyword","store":true},
9 "edu":{"type":"keyword","store":true},
10 "salary":{"type":"keyword","store":true},
11 "job_type":{"type":"keyword","store":true},
12 "cmp":{"type":"keyword","store":true},
13 "pv":{"type":"keyword","store":true},
14 "title":{"type":"text","store":true},
15 "jd":{"type":"text"}
16
17 }
18 },
19 "settings":{
20 "number_of_shards":3,
21 "number_of_replicas":2
22 }
23 }
24
25 // 查看分片、主分片、副本分片
26 GET /_cat/indices?v

三、Elasticsearch重要工作流程

3.1 Elasticsearch文档写入原理

1.选择任意一个DataNode发送请求,例如:node2。此时,node2就成为一个

coordinating node(协调节点)

2.计算得到文档要写入的分片

`shard = hash(routing) % number_of_primary_shards`

routing 是一个可变值,默认是文档的 _id

3.coordinating node会进行路由,将请求转发给对应的primary shard所在的

DataNode(假设primary shard在node1、replica shard在node2)

4.node1节点上的Primary Shard处理请求,写入数据到索引库中,并将数据同步到

Replica shard

5.Primary Shard和Replica Shard都保存好了文档,返回clien

3.2 Elasticsearch检索原理

client发起查询请求,某个DataNode接收到请求,该DataNode就会成为协调节点

(Coordinating Node)

协调节点(Coordinating Node)将查询请求广播到每一个数据节点,这些数据节

点的分片会处理该查询请求

每个分片进行数据查询,将符合条件的数据放在一个优先队列中,并将这些数据

的文档ID、节点信息、分片信息返回给协调节点

协调节点将所有的结果进行汇总,并进行全局排序

协调节点向包含这些文档ID的分片发送get请求,对应的分片将文档数据返回给协

调节点,最后协调节点将数据返回给客户端

四、Elasticsearch准实时索引实现

4.1 溢写到文件系统缓存

当数据写入到ES分片时,会首先写入到内存中,然后通过内存的buffer生成一个

segment,并刷到文件系统缓存中,数据可以被检索(注意不是直接刷到磁盘)

ES中默认1秒,refresh一次

4.2 写translog保障容错

在写入到内存中的同时,也会记录translog日志,在refresh期间出现异常,会根

据translog来进行数据恢复

等到文件系统缓存中的segment数据都刷到磁盘中,清空translog文件

4.3 flush到磁盘

ES默认每隔30分钟会将文件系统缓存的数据刷入到磁盘

4.4 segment合并

Segment太多时,ES定期会将多个segment合并成为大的segment,减少索引查询时

IO开销,此阶段ES会真正的物理删除(之前执行过的delete的数据)

五.手工控制搜索结果精准度

bash 复制代码
5.1、下述搜索中,如果document中的remark字段包含java或developer词组,都符
合搜索条件。
1 GET /es_db/_search
2 {
3 "query": {
4 "match": {
5 "remark": "java developer"
6 }
7 }
8 }
如果需要搜索的document中的remark字段,包含java和developer词组,则需要使
用下述语法:
1 GET /es_db/_search
2 {
3 "query": {
4 "match": {
5 "remark": {
6 "query": "java developer",
7 "operator": "and"
8 }
9 }
10 }
11 }
上述语法中,如果将operator的值改为or。则与第一个案例搜索语法效果一致。默
认的ES执行搜索的时候,operator就是or。
如果在搜索的结果document中,需要remark字段中包含多个搜索词条中的一定比
例,可以使用下述语法实现搜索。其中minimum_should_match可以使用百分比或固
定数字。百分比代表query搜索条件中词条百分比,如果无法整除,向下匹配
(如,query条件有3个单词,如果使用百分比提供精准度计算,那么是无法除尽
的,如果需要至少匹配两个单词,则需要用67%来进行描述。如果使用66%描述,ES
则认为匹配一个单词即可。)。固定数字代表query搜索条件中的词条,至少需要
匹配多少个。
1 GET /es_db/_search
2 {
3 "query": {
4 "match": {
5 "remark": {
6 "query": "java architect assistant",
7 "minimum_should_match": "68%"
8 }
9 }
10 }
11 }
如果使用should+bool搜索的话,也可以控制搜索条件的匹配度。具体如下:下述
案例代表搜索的document中的remark字段中,必须匹配java、developer、
assistant三个词条中的至少2个。
1 GET /es_db/_search
2 {
3 "query": {
4 "bool": {
5 "should": [
6 {
7 "match": {
8 "remark": "java"
9 }
10 },
11 {
12 "match": {
13 "remark": "developer"
14 }
15 },
16 {
17 "match": {
18 "remark": "assistant"
19 }
20 }
21 ],
22 "minimum_should_match": 2
23 }
24 }
25 }

5.2、match 的底层转换

bash 复制代码
其实在ES中,执行match搜索的时候,ES底层通常都会对搜索条件进行底层转换,
来实现最终的搜索结果。如:
1 GET /es_db/_search
2 {
3 "query": {
4 "match": {
5 "remark": "java developer"
6 }
7 }
8 }
9
10 转换后是:
11 GET /es_db/_search
12 {
13 "query": {
14 "bool": {
15 "should": [
16 {
17 "term": {
18 "remark": "java"
19 }
20 },
21 {
22 "term": {
23 "remark": {
24 "value": "developer"
25 }
26 }
27 }
28 ]
29 }
30 }
31 }
1 GET /es_db/_search
2 {
3 "query": {
4 "match": {
5 "remark": {
6 "query": "java developer",
7 "operator": "and"
8 }
9 }
10 }
11 }
12
13 转换后是:
14 GET /es_db/_search
15 {
16 "query": {
17 "bool": {
18 "must": [
19 {
20 "term": {
21 "remark": "java"
22 }
23 },
24 {
25 "term": {
26 "remark": {
27 "value": "developer"
28 }
29 }
30 }
31 ]
32 }
33 }
34 }
1 GET /es_db/_search
2 {
3 "query": {
4 "match": {
5 "remark": {
6 "query": "java architect assistant",
7 "minimum_should_match": "68%"
8 }
9 }
10 }
11 }
12
13 转换后为:
14 GET /es_db/_search
15 {
16 "query": {
17 "bool": {
18 "should": [
19 {
20 "term": {
21 "remark": "java"
22 }
23 },
24 {
25 "term": {
26 "remark": "architect"
27 }
28 },
29 {
30 "term": {
31 "remark": "assistant"
32 }
33 }
34 ],
35 "minimum_should_match": 2
36 }
37 }
38 }

5.3、boost权重控制

搜索document中remark字段中包含java的数据,如果remark中包含developer

或architect,则包含architect的document优先显示。(就是将architect数据匹

配时的相关度分数增加)。

一般用于搜索时相关度排序使用。如:电商中的综合排序。将一个商品的销

量,广告投放,评价值,库存,单价比较综合排序。在上述的排序元素中,广告投

放权重最高,库存权重最低。

bash 复制代码
GET /es_db/_search
2 {
3 "query": {
4 "bool": {
5 "must": [
6 {
7 "match": {
8 "remark": "java"
9 }
10 }
11 ],
12 "should": [
13 {
14 "match": {
15 "remark": {
16 "query": "developer",
17 "boost" : 1
18 }
19 }
20 },
21 {
22 "match": {
23 "remark": {
24 "query": "architect",
25 "boost" : 3
26 }
27 }
28 }
29 ]
30 }
31 }
32 }

5.4、基于dis_max实现best fields策略进行多字段搜索

best fields策略: 搜索的document中的某一个field,尽可能多的匹配搜索

条件。与之相反的是,尽可能多的字段匹配到搜索条件(most fields策略)。如

百度搜索使用这种策略。

优点:精确匹配的数据可以尽可能的排列在最前端,且可以通过

minimum_should_match来去除长尾数据,避免长尾数据字段对排序结果的影响。

长尾数据比如说我们搜索4个关键词,但很多文档只匹配1个,也显示出来了,这些文

档其实不是我们想要的

缺点:相对排序不均匀。

dis_max语法: 直接获取搜索的多条件中的,单条件query相关度分数最

高的数据,以这个数据做相关度排序。

下述的案例中,就是找name字段中rod匹配相关度分数或remark字段中java

developer匹配相关度分数,哪个高,就使用哪一个相关度分数进行结果排序。

bash 复制代码
1 GET /es_db/_search
2 {
3 "query": {
4 "dis_max": {
5 "queries": [
6 {
7 "match": {
8 "name": "rod"
9 }
10 },
11 {
12 "match": {
13 "remark": "java developer"
14 }
15 }
16 ]
17 }
18 }
19 }

5.5、基于tie_breaker参数优化dis_max搜索效果

dis_max是将多个搜索query条件中相关度分数最高的用于结果排序,忽略其他

query分数,在某些情况下,可能还需要其他query条件中的相关度介入最终的结果

排序,这个时候可以使用tie_breaker参数来优化dis_max搜索。tie_breaker参数

代表的含义是:将其他query搜索条件的相关度分数乘以参数值,再参与到结果排

序中。如果不定义此参数,相当于参数值为0。所以其他query条件的相关度分数被

忽略。

bash 复制代码
1 GET /es_db/_search
2 {
3 "query": {
4 "dis_max": {
5 "queries": [
6 {
7 "match": {
8 "name": "rod"
9 }
10 },
11 {
12 "match": {
13 "remark": "java developer"
14 }
15 }
16 ],
17 "tie_breaker":0.5
18 }
19 }
20 }

5.6、使用multi_match简化dis_max+tie_breaker

bash 复制代码
1 GET /es_db/_search
2 {
3 "query": {
4 "dis_max": {
5 "queries": [
6 {
7 "match": {
8 "name": "rod"
9 }
10 },
11 {
12 "match": {
13 "remark": {
14 "query": "java developer",
15 "boost" : 2,
16 "minimum_should_match": 2
17 }
18 }
19 }
20 ],
21 "tie_breaker": 0.5
22 }
23 }
24 }
25
26 #使用multi_match语法为:其中type常用的有best_fields和most_fields。^n代表权重,
相当于"boost":n。
27 GET /es_db/_search
28 {
29 "query": {
30 "multi_match": {
31 "query": "rod java developer",
32 "fields": ["name", "remark^2"],
33 "type": "best_fields",
34 "tie_breaker": 0.5,
35 "minimum_should_match" : "50%"
36 }
37 }
38 }
相关推荐
北上ing25 分钟前
算法练习:19.JZ29 顺时针打印矩阵
算法·leetcode·矩阵
国际云,接待1 小时前
云服务器的运用自如
服务器·架构·云计算·腾讯云·量子计算
.格子衫.2 小时前
真题卷001——算法备赛
算法
XiaoyaoCarter2 小时前
每日一道leetcode
c++·算法·leetcode·职场和发展·二分查找·深度优先·前缀树
Blossom.1182 小时前
使用Python实现简单的人工智能聊天机器人
开发语言·人工智能·python·低代码·数据挖掘·机器人·云计算
da-peng-song2 小时前
ArcGIS Desktop使用入门(二)常用工具条——数据框工具(旋转视图)
开发语言·javascript·arcgis
galaxy_strive2 小时前
qtc++ qdebug日志生成
开发语言·c++·qt
遇见火星2 小时前
jenkins流水线常规配置教程!
运维·docker·jenkins
TNTLWT2 小时前
Qt功能区:简介与安装
开发语言·qt
Hygge-star2 小时前
【数据结构】二分查找5.12
java·数据结构·程序人生·算法·学习方法