一、基础知识了解:
-
数据路由(documnet routing)
当客户端发起创建document的时候,es需要确定这个document放在该index哪个shard上。这个过程就是数据路由。
路由过程:
路由算法:shard = hash(routing) % number_of_primary_shards
routing:每次增删改查一个document的时候,都会带过来一个routing number,他的默认值就是这个document的_id(可能是手动指定,也可能是自动生成)routing = _id,所以决定一个document在哪个shard上,最重要的一个值就是routing值。相同的routing值,从hash函数中,产出的hash值一定是相同的。
number_of_primary_shards:主分片。
例如:假设 _id=1会将这个routing值,传入一个hash函数中,产出一个routing值的hash值,hash(routing) = 21,然后将hash函数产出的值对这个index的primaryshard的数量求余数,21 % 3 = 0 就决定了,这个document就放在P0上。
手动指定routing:PUT /index/type/id?routing=user_id
手动指定routing value,可以保证某一类document一定被路由到一个shard上去,那么在后续进行应用级别的负载均衡以及提升批量读取的性能的时候,是很有帮助的。 -
primary shard数量不可变
假如我们的集群在初始化的时候有5个primary shard,我们望里边加入一个document id=5,假如hash(5)=23,这时该document 将被加入 (shard=23%5=3)P3这个分片上。如果随后我们给es集群添加一个primary shard ,此时就有6个primary shard,当我们GET id=5 ,这条数据的时候,es会计算该请求的路由信息找到存储他的 primary shard(shard=23%6=5) ,根据计算结果定位到P5分片上。而我们的数据在P3上。所以es集群无法添加primary shard,但是可以扩展replicas shard。 -
数据恢复(recovery)
代表数据恢复或叫数据重新分布,es在有节点加入或退出时会根据机器的负载对索引分片进行重新分配,挂掉的节点重新启动时也会进行数据恢复。
GET /_cat/health?v #可以看到集群状态 -
通信(Transport)
代表es内部节点或集群与客户端的交互方式,默认内部是使用tcp协议进行交互,同时它支持http协议(json格式)、thrift、servlet、memcached、zeroMQ等的传输协议(通过插件方式集成)。
节点间通信端口默认:9300-9400 -
document增删改的处理流程
ES增删改的处理流程:增删该的请求一定作用在主分片上。
假如我们es集群有3个node,每个node上一个主分片一个复制分片。
1、客户端发起一个PUT请求,假如该请求被发送到第一个node节点,那么该节点将成为协调节点(coordinating node),如图P1所在的节点就是协调节点。他将根据该请求的路由信息计算,该document将被存储到哪个分片。
2、第二步 通过计算发现该document被存储到p0分片,那么就将请求转发到node2节点。
3、第三步 P0根据请求信息创建document,和相应的索引信息,创建完毕后将信息同步到自己的副本节点R0上。
4、第四步 P0和R0将通知我们的协调节点,任务完成情况。
5、第五部 协调节点响应客户端最终的处理结果。
6. document读请求流程
1、第一步客户端发送读器请求到协调节点(coordinate node)。
2、第二步协调节点(coordinate node)根据请求信息对document进行路由计算,将请求转发到对应的node,node2 或者node3。 此时会使用round-robin随机轮询算法,在primary shard以及其所有replica(副本)中随机选择一个,让读请求负载均衡。
3、第三步相应接收到请求的节点(node2或者node3)将处理结果返回给协调节点(coordinate node)。
4、协调节点将最终的结果反馈给客户端。
注意:document如果还在建立索引过程中,可能只有primary shard有,任何一个replica shard都没有,此时请求如果作用到replica shard上可能会导致无法读取到document信息。但是document完成索引建立之后,primary shard和replica shard就都有了。
7. elasticsearch . yml
# 设置节点间交互的tcp端口,默认是9300
# transport.tcp.port: 9300
# 设置对外服务的http端口,默认为9200
# http.port: 9200
# Translog部分:
# 每一个分片(shard)都有一个transaction log或者是与它有关的预写日志,(write log),在es进行索引(index)或者删除(delete)操作时会将没有提交的数据记录在translog之中,当进行flush 操作的时候会将tranlog中的数据发送给Lucene进行相关的操作.一次flush操作的发生基于如下的几个配置
#index.translog.flush_threshold_ops:当发生多少次操作时进行一次flush.默认是 unlimited #index.translog.flush_threshold_size:当translog的大小达到此值时会进行一次flush操作.默认是512mb
#index.translog.flush_threshold_period:在指定的时间间隔内如果没有进行flush操作,会进行一次强制flush操作.默认是30m
#index.translog.interval:多少时间间隔内会检查一次translog,来进行一次flush操作.es会随机的在这个值到这个值的2倍大小之间进行一次操作,默认是5s#index.gateway.local.sync:多少时间进行一次的写磁盘操作,默认是5s
#设置索引的分片数,默认为5
#index.number_of_shards: 5
#设置索引的副本数,默认为1:
#index.number_of_replicas: 1#配置文件中提到的最佳实践是,如果服务器够多,可以将分片提高,尽量将数据平均分布到大集群中去
#同时,如果增加副本数量可以有效的提高搜索性能
#需要注意的是,“number_of_shards” 是索引创建后一次生成的,后续不可更改设置
#“number_of_replicas” 是可以通过API去实时修改设置的
二、索引、类型、文档
- 索引
索引的名字必须是全部小写,不能以下划线开头,不能包含逗号
在Elasticsearch中,文档(document)这个术语有着特殊含义。它特指最顶层结构或者根对象(root object)序列化成的JSON数据(以唯一ID标识并存储于Elasticsearch中)。
文档由字段组成,相当于关系数据库中列的属性,不同的是ES的不同文档可以具有不同的字段集合。
对比关系型数据库:
Relational DB -> Databases -> Tables -> Rows -> Columns
Elasticsearch -> Indices -> Types -> Documents -> Fields - 文档元数据
_index:索引 文档存储的地方
_type:类型 文档代表的对象的类
_id:id仅仅是一个字符串,它与_index和_type组合时,就可以在Elasticsearch中唯一标识一个文档。 文档的唯一标识
三、写操作(Write):针对文档的CRUD操作 - 索引新文档(Create)
当用户向一个节点提交了一个索引新文档的请求,节点会计算新文档应该加入到哪个分片(shard)中。每个节点都存储有每个分片存储在哪个节点的信息,因此协调节点会将请求发送给对应的节点。注意这个请求会发送给主分片,等主分片完成索引,会并行将请求发送到其所有副本分片,保证每个分片都持有最新数据。
每次写入新文档时,都会先写入内存中,并将这一操作写入一个translog文件(transaction log)中,此时如果执行搜索操作,这个新文档还不能被索引到。
ES会每隔1秒时间(这个时间可以修改)进行一次刷新操作(refresh),此时在这1秒时间内写入内存的新文档都会被写入一个文件系统缓存(filesystem cache)中,并构成一个分段(segment)。此时这个segment里的文档可以被搜索到,但是尚未写入硬盘,即如果此时发生断电,则这些文档可能会丢失。
不断有新的文档写入,则这一过程将不断重复执行。每隔一秒将生成一个新的segment,而translog文件将越来越大。
每隔30分钟或者translog文件变得很大,则执行一次fsync操作。此时所有在文件系统缓存中的segment将被写入磁盘,而translog将被删除(此后会生成新的translog)。
由上面的流程可以看出,在两次fsync操作之间,存储在内存和文件系统缓存中的文档是不安全的,一旦出现断电这些文档就会丢失。所以ES引入了translog来记录两次fsync之间所有的操作,这样机器从故障中恢复或者重新启动,ES便可以根据translog进行还原。
translog本身也是文件,存在于内存当中,如果发生断电一样会丢失。因此,ES会在每隔5秒时间或是一次写入请求完成后将translog写入磁盘。只有在当前操作记录被写入磁盘,ES才会将操作成功的结果返回发送此操作请求的客户端。
由于每一秒就会生成一个新的segment,很快将会有大量的segment。对于一个分片进行查询请求,将会轮流查询分片中的所有segment,这将降低搜索的效率。因此ES会自动启动合并segment的工作,将一部分相似大小的segment合并成一个新的大segment。合并的过程实际上是创建了一个新的segment,当新segment被写入磁盘,所有被合并的旧segment被清除。 - 更新(Update)和删除(Delete)文档
ES的索引是不能修改的,因此更新和删除操作并不是直接在原索引上直接执行。
每一个磁盘上的segment都会维护一个del文件,用来记录被删除的文件。每当用户提出一个删除请求,文档并没有被真正删除,索引也没有发生改变,而是在del文件中标记该文档已被删除。因此,被删除的文档依然可以被检索到,只是在返回检索结果时被过滤掉了。每次在启动segment合并工作时,那些被标记为删除的文档才会被真正删除。
更新文档会首先查找原文档,得到该文档的版本号。然后将修改后的文档写入内存,此过程与写入一个新文档相同。同时,旧版本文档被标记为删除,同理,该文档可以被搜索到,只是最终被过滤掉。
四、读操作(Read):查询过程
查询的过程大体上分为查询(query)和取回(fetch)两个阶段。这个节点的任务是广播查询请求到所有相关分片,并将它们的响应整合成全局排序后的结果集合,这个结果集合会返回给客户端。
查询阶段
当一个节点接收到一个搜索请求,则这个节点就变成了协调节点。
第一步是广播请求到索引中每一个节点的分片拷贝。 查询请求可以被某个主分片或某个副本分片处理,协调节点将在之后的请求中轮询所有的分片拷贝来分摊负载。
每个分片将会在本地构建一个优先级队列。如果客户端要求返回结果排序中从第from名开始的数量为size的结果集,则每个节点都需要生成一个from+size大小的结果集,因此优先级队列的大小也是from+size。分片仅会返回一个轻量级的结果给协调节点,包含结果集中的每一个文档的ID和进行排序所需要的信息。
协调节点会将所有分片的结果汇总,并进行全局排序,得到最终的查询排序结果。此时查询阶段结束。
取回阶段
查询过程得到的是一个排序结果,标记出哪些文档是符合搜索要求的,此时仍然需要获取这些文档返回客户端。
协调节点会确定实际需要返回的文档,并向含有该文档的分片发送get请求;分片获取文档返回给协调节点;协调节点将结果返回给客户端。
五、运行kibana
/usr/elasticsearch/kibana/kibana-6.4.0-linux-x86_64/bin
sh kibana
获取所有数据:
GET /_search
返回结果:
{
"took": 76,
"timed_out": false,
"_shards": {
"total": 16,
"successful": 16,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 8,
"max_score": 1,
"hits": [
{
"_index": ".kibana",
"_type": "doc",
"_id": "config:6.4.0",
"_score": 1,
"_source": {
"type": "config",
"updated_at": "2018-09-18T09:30:18.949Z",
"config": {
"buildNum": 17929,
"telemetry:optIn": true
}
}
},
{
"_index": "blog",
"_type": "article",
"_id": "eTmX5mUBtZGWutGW0TNs",
"_score": 1,
"_source": {
"title": "New version of Elasticsearch released!",
"content": "Version 1.0 released today!",
"priority": 10,
"tags": [
"announce",
"elasticsearch",
"release"
]
}
},
{
"_index": "ecommerce",
"_type": "product",
"_id": "2",
"_score": 1,
"_source": {
"name": "jiajieshi yagao",
"desc": "youxiao fangzhu",
"price": 25,
"producer": "jiajieshi producer",
"tags": [
"fangzhu"
]
}
},
{
"_index": "ecommerce",
"_type": "product",
"_id": "J3fLFWYBBoLynJN1-kOG",
"_score": 1,
"_source": {
"name": "test yagao",
"desc": "youxiao fangzhu"
}
},
{
"_index": "blog",
"_type": "article",
"_id": "1",
"_score": 1,
"_source": {
"id": "1",
"title": "New version of Elasticsearch released!",
"content": "Version 1.0 released today!",
"priority": 10,
"tags": [
"announce",
"elasticsearch",
"release"
]
}
},
{
"_index": "ecommerce",
"_type": "product",
"_id": "KXfSFWYBBoLynJN1TUPo",
"_score": 1,
"_source": {
"name": "test yagao2",
"desc": "youxiao fangzhu2"
}
},
{
"_index": "index",
"_type": "fulltext",
"_id": "1",
"_score": 1,
"_source": {
"content": "中国驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首"
}
},
{
"_index": "ecommerce",
"_type": "product",
"_id": "3",
"_score": 1,
"_source": {
"name": "zhonghua yagao",
"desc": "caoben zhiwu",
"price": 40,
"producer": "zhonghua producer",
"tags": [
"qingxin"
]
}
}
]
}
}
取出数据含义:
took:耗费了几毫秒 timed_out:是否超时,false是没有,默认无timeout
_shards:shards fail的条件(primary和replica全部挂掉),不影响其他shard。默认情况下来说,一个搜索请求,会打到一个index的所有primary
shard上去,当然了,每个primary shard都可能会有一个或多个replic shard,所以请求也可以到primary
shard的其中一个replica shard上去。 hits.total:本次搜索,返回了几条结果
hits.max_score:score的含义,就是document对于一个search的相关度的匹配分数,越相关,就越匹配,分数也高
hits.hits:包含了匹配搜索的document的详细数据,默认查询前10条数据,按_score降序排序
参考链接https://blog.csdn.net/gwd1154978352/article/details/82804942