1、Elastic Stack简介
如果你没有听说过Elastic Stack,那你一定听说过ELK,实际上ELK是三款软件的简称,分别是Elasticsearch、
Logstash、Kibana组成,在发展的过程中,又有新成员Beats的加入,所以就形成了Elastic Stack。所以说,ELK是旧的称呼,Elastic Stack是新的名字。
* Elasticsearch
Elasticsearch 基于java,是个开源分布式搜索引擎,它的特点有:分布式,零配置,自动发现,索引自动分片,索引
副本机制,restful风格接口,多数据源,自动搜索负载等。
* Logstash
Logstash 基于java,是一个开源的用于收集,分析和存储日志的工具。
* Kibana
Kibana 基于nodejs,也是一个开源和免费的工具,Kibana可以为 Logstash 和 ElasticSearch 提供的日志分析友好的
Web 界面,可以汇总、分析和搜索重要数据日志。
* Beats
Beats是elastic公司开源的一款采集系统监控数据的代理agent,是在被监控服务器上以客户端形式运行的数据收集
器的统称,可以直接把数据发送给Elasticsearch或者通过Logstash发送给Elasticsearch,然后进行后续的数据分析活
动。
Beats由如下组成:
1. Packetbeat:是一个网络数据包分析器,用于监控、收集网络流量信息,Packetbeat嗅探服务器之间的流量,
解析应用层协议,并关联到消息的处理,其支 持ICMP (v4 and v6)、DNS、HTTP、Mysql、PostgreSQL、Redis、MongoDB、Memcache等协议;
2. Filebeat:用于监控、收集服务器日志文件,其已取代 logstash forwarder;
3. Metricbeat:可定期获取外部系统的监控指标信息,其可以监控、收集 Apache、HAProxy、MongoDB
MySQL、Nginx、PostgreSQL、Redis、System、Zookeeper等服务;
4. Winlogbeat:用于监控、收集Windows系统的日志信息;
2、Elasticsearch
2.1、简介
ElasticSearch是一个基于Lucene的搜索服务器。 它提供了一一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。
官网:https://www.elastic.co/cn/elasticsearch
2.2、安装
下载地址::https://www.elastic.co/cn/downloads/elasticsearch
解压即可
点击bin目录下的elasticsearch.bat即可启动服务器,
http://localhost:9200/
访问得到相关的版本信息
解决允许跨域访问
在 /config/elasticsearch.yml 文件最后添加如下代码
http.cors.enabled: true http.cors.allow-origin: "*"
2.3、可视化工具elasticsearch-head
由于ES官方并没有为ES提供界面管理工具,仅仅是提供了后台的服务。elasticsearch-head是一个为ES开发的一个页面客户端工具,其源码托管于GitHub,
地址为:https://github.com/mobz/elasticsearch-head
安装启动
1. 首先要有node环境
2. 使用npm install安装模块包
3. npm run srart即可后台启动elasticsearch-head的服务器
4. 使用 http://localhost:9100 即可访问可视化页面
2.4、基本概念
索引
- 索引(index)是Elasticsearch对逻辑数据的逻辑存储,所以它可以分为更小的部分。
- 可以把索引看成关系型数据库的表,索引的结构是为快速有效的全文索引准备的,特别是它不存储原始值。
- Elasticsearch可以把索引存放在一台机器或者分散在多台服务器上,每个索引有一或多个分片(shard),每个
分片可以有多个副本(replica)。
文档
- 存储在Elasticsearch中的主要实体叫文档(document)。用关系型数据库来类比的话,一个文档相当于数据库表中的一行记录。
- Elasticsearch和MongoDB中的文档类似,都可以有不同的结构,但Elasticsearch的文档中,相同字段必须有相同类型。
- 文档由多个字段组成,每个字段可能多次出现在一个文档里,这样的字段叫多值字段(multivalued)。
- 每个字段的类型,可以是文本、数值、日期等。字段类型也可以是复杂类型,一个字段包含其他子文档或者数组。
映射
- 所有文档写进索引之前都会先进行分析,如何将输入的文本分割为词条、哪些词条又会被过滤,这种行为叫做映射(mapping)。一般由用户自己定义规则。
文档类型
- 在Elasticsearch中,一个索引对象可以存储很多不同用途的对象。例如,一个博客应用程序可以保存文章和评论。
- 每个文档可以有不同的结构。
- 不同的文档类型不能为相同的属性设置不同的类型。例如,在同一索引中的所有文档类型中,一个叫title的字段必须具有相同的类型。
2.5、RESTful API
在Elasticsearch中,提供了功能丰富的RESTful API的操作,包括基本的CRUD、创建索引、删除索引等操作。
2.5.1、创建非结构化索引
在Lucene中,创建索引是需要定义字段名称以及字段的类型的,在Elasticsearch中提供了非结构化的索引,就是不需要创建索引结构,即可写入数据到索引中,实际上在Elasticsearch底层会进行结构化操作,此操作对用户是透明的。
创建空索引:
put: 127.0.0.1:9200/hello #第一个参数:分片数 #第二个参数:副本数 { "settings":{ "index":{ "number_of_shards":"2", "number_of_replicas":"0" } } } #删除索引 DELETE: 127.0.0.1:9200/hello { "acknowledged": true }
2.5.2、插入数据
URL规则:
POST /{索引}/{类型}/{id}
POST 127.0.0.1:9200/hello/user/1001 #数据 { "id":1001, "name":"张三", "age":20, "sex":"男" } #响应 { "_index":"haoke", "_type":"user", "_id":"1", "_version":1, "result":"created", "_shards":{ "total":1, "successful":1, "failed":0 }, "_seq_no":0, "_primary_term":1 }
不指定id插入数据:
POST 127.0.0.1:9200/hello/user/ { "id":1002, "name":"张三", "age":20, "sex":"男" }
2.5.3、更新数据
在Elasticsearch中,文档数据是不为修改的,但是可以通过覆盖的方式进行更新。
PUT 127.0.0.1:9200/hello/user/1001 { "id":1001, "name":"张三", "age":21, "sex":"女" }
这时到数据已经被覆盖了,如果有字段没有值,那么值就为空
如果要局部更新
#注意:这里多了_update标识和"doc" POST 127.0.0.1:9200/hello/user/1001_update { "doc":{ "age":23 } }
可以看到数据已经被局部更新了。
2.5.4、删除数据
在Elasticsearch中,删除文档数据,只需要发起DELETE请求即可。
DELETE 127.0.0.1:9200/hello/user/1001
需要注意的是,result表示已经删除,version也更加了。
如果删除一条不存在的数据,会响应404:
2.5.5、搜索数据
- 根据id搜索数据
Get 127.0.0.1:9200/hello/user/1001 #响应数据 { "_index": "hello", "_type": "user", "_id": "1001", "_version": 3, "found": true, "_source": { "id": 1001, "name": "张三", "age": 66, "sex": "女" } }
- 搜索全部数据
Get 127.0.0.1:9200/hello/user/1001 - 关键字搜素数据
#查询年龄等于20的用户 GET 127.0.0.1:9200/hello/user/_search?q=age:20
2.5.6、DSL搜索
Elasticsearch提供丰富且灵活的查询语言叫做DSL查询(Query DSL),它允许你构建更加复杂、强大的查询。
DSL(Domain Specific Language特定领域语言)以JSON请求体的形式出现。
#实现:查询年龄等于20的用户 POST 127.0.0.1:9200/hello/user/_search #请求体 { "query":{ "match":{ "age":"20" } } } #实现:查询年龄大于30岁的男性用户。 POST 127.0.0.1:9200/hello/user/_search #请求体 { "query":{ "bool":{ "filter":{ "range":{ "age":{ "gt":25 } } }, "must":{ "match":{ "sex":"男" } } } } } #实现:高亮显示 POST 127.0.0.1:9200/hello/user/_search #请求体 { "query":{ "match":{ "name":"张三 李四" } }, "highlight":{ "fields":{ "name":{ } } } } #实现:聚合 在Elasticsearch中,支持聚合操作,类似SQL中的group by操作。 POST 127.0.0.1:9200/hello/user/_search #请求体 { "aggs":{ "all_interests":{ "terms":{ "field":"age" } } } }
索引
{ "settings":{ "index":{ "number_of_shards":"2", "number_of_replicas":"0" } }, "mappings":{ "person":{ "properties":{ "name":{ "type":"text" }, "age":{ "type":"integer" }, "mail":{ "type":"keyword" }, "hobby":{ "type":"text" } } } } }
3、核心详解
3.1、文档
在Elasticsearch中,文档以JSON格式进行存储,可以是复杂的结构
* 元数据(metadata)
一个文档不只有数据。它还包含了元数据(metadata)——关于文档的信息。三个必须的元数据节点是:
* _index
索引(index)类似于关系型数据库里的“数据库”——它是我们存储和索引关联数据的地方
* _type
每个类型(type)都有自己的映射(mapping)或者结构定义,就像传统数据库表中的列一样。所有类型下的文档被存储在同一个索引下,但是类型的映射(mapping)会告诉Elasticsearch不同的文档如何被索引。
_type 的名字可以是大写或小写,不能包含下划线或逗号。我们将使用 blog 做为类型名。
* _id
id仅仅是一个字符串,它与 _index 和 _type 组合时,就可以在Elasticsearch中唯一标识一个文档。当创建一个文
档,你可以自定义 _id ,也可以让Elasticsearch帮你自动生成(32位长度)。
3.2、查询响应
3.2.1、pretty
可以在查询url后面添加pretty参数,使得返回的json更易查看。
3.2.2、指定响应字段
在响应的数据中,如果我们不需要全部的字段,可以指定某些需要的字段进行返回
GET http://127.0.0.1:9200/itcast/person/If6JeXEBTDVmGkzkSswT?_source=age,name 响应数据 { "_index": "itcast", "_type": "person", "_id": "If6JeXEBTDVmGkzkSswT", "_version": 1, "found": true, "_source": { "name": "张三", "age": 20 } }
如不需要返回元数据,仅仅返回原始数据,可以这样:
GET http://127.0.0.1:9200/itcast/person/If6JeXEBTDVmGkzkSswT/_source #响应数据 { "name": "张三", "age": 20, "mail": "111@qq.com", "hobby": "羽毛球、乒乓球、足球" } 还可以这样: GET http://127.0.0.1:9200/itcast/person/If6JeXEBTDVmGkzkSswT/_source?_source=age,name #响应数据 { "name": "张三", "age": 20 }
3.3、判断文档是否存在
如果我们只需要判断文档是否存在,而不是查询文档内容,那么可以这样:
HEAD http://127.0.0.1:9200/itcast/person/1001/
如果文档存在:响应头信息状态码200
如果文档不存在:响应头信息状态码404
3.4、批量操作
有些情况下可以通过批量操作以减少网络请求。如:批量查询、批量插入数据。
3.4.1、批量查询
_mget
http://127.0.0.1:9200/itcast/person/_mget { "ids" : [ "1001", "1003" ] }
如果,某一条数据不存在,不影响整体响应,需要通过found的值进行判断是否查询到数据。
3.4.2、_bulk操作
在Elasticsearch中,支持批量的插入、修改、删除操作,都是通过_bulk的api完成的。
请求格式如下:(请求格式不同寻常)
{ action: { metadata }}\n { request body }\n { action: { metadata }}\n { request body }\n ...(这个一定要有一个换行)
注意:末尾一定要有一个换行
1. 批量插入数据:
POST 127.0.0.1:9200/itcast/_bulk {"create":{"_index":"haoke","_type":"user","_id":2001}} {"id":2001,"name":"name1","age": 20,"sex": "男"} {"create":{"_index":"haoke","_type":"user","_id":2002}} {"id":2002,"name":"name2","age": 20,"sex": "男"} {"create":{"_index":"haoke","_type":"user","_id":2003}} {"id":2003,"name":"name3","age": 20,"sex": "男"}
- 批量删除:
POST 127.0.0.1:9200/itcast/_bulk {"delete":{"_index":"haoke","_type":"user","_id":2001}} {"delete":{"_index":"haoke","_type":"user","_id":2002}} {"delete":{"_index":"haoke","_type":"user","_id":2003}}
由于delete没有请求体,所以,action的下一行直接就是下一个action。
其他操作类似。
一次请求多少性能最高?
通常着眼于你请求批次的物理大小是非常有用的。一千个1kB的文档和一千个1MB的文档大不相同。一个好的
批次最好保持在5-15MB大小间。
3.5、分页
和SQL使用 LIMIT 关键字返回只有一页的结果一样,Elasticsearch接受 from 和 size 参数:
size: 结果数,默认10
from: 跳过开始的结果数,默认0
如果你想每页显示5个结果,页码从1到3,那请求如下:
GET /_search?size=5 GET /_search?size=5&from=5 GET /_search?size=5&from=10 GET 127.0.0.1:9200/hello/user/_search?size=2&from=2
应该当心分页太深或者一次请求太多的结果。结果在返回前会被排序。但是记住一个搜索请求常常涉及多个分
片。每个分片生成自己排好序的结果,它们接着需要集中起来排序以确保整体排序正确。
在集群系统中深度分页
们假设在一个有5个主分片的索引中搜索。当我们请求结果的第一
页(结果1到10)时,每个分片产生自己最顶端10个结果然后返回它们给请求节点(requesting node),它再
排序这所有的50个结果以选出顶端的10个结果。
现在假设我们请求第1000页——结果10001到10010。工作方式都相同,不同的是每个分片都必须产生顶端的
10010个结果。然后请求节点排序这50050个结果并丢弃50040个!
你可以看到在分布式系统中,排序结果的花费随着分页的深入而成倍增长。这也是为什么网络搜索引擎中任何
语句不能返回多于1000个结果的原因。
3.6、映射
前面我们创建的索引以及插入数据,都是由Elasticsearch进行自动判断类型,有些时候我们是需要进行明确字段类型的,否则,自动判断的类型和实际需求是不相符的。
自动判断的规则如下:
Elasticsearch中支持的类型如下:
注意
* string类型在ElasticSearch 旧版本中使用较多,从ElasticSearch 5.x开始不再支持string,由text和
keyword类型替代。
* text 类型,当一个字段是要被全文搜索的,比如Email内容、产品描述,应该使用text类型。设置text类型
以后,字段内容会被分析,在生成倒排索引以前,字符串会被分析器分成一个一个词项。text类型的字段
不用于排序,很少用于聚合。
* keyword类型适用于索引结构化的字段,比如email地址、主机名、状态码和标签。如果字段需要进行过
滤(比如查找已发布博客中status属性为published的文章)、排序、聚合。keyword类型的字段只能通过精
确值搜索到。
创建明确类型的索引:
PUT`127.0.0.1:9200/itcast { "settings":{ "index":{ "number_of_shards":"2", "number_of_replicas":"0" } }, "mappings":{ "person":{ "properties":{ "name":{ "type":"text" }, "age":{ "type":"integer" }, "mail":{ "type":"keyword" }, "hobby":{ "type":"text" } } } } }
查看映射:
GET 127.0.0.1:9200/itcast/_mapping
插入数据:
POST 127.0.0.1:9200/itcast/_bulk {"index":{"_index":"itcast","_type":"person"}} {"name":"张三","age": 20,"mail": "111@qq.com","hobby":"羽毛球、乒乓球、足球"} {"index":{"_index":"itcast","_type":"person"}} {"name":"李四","age": 21,"mail": "222@qq.com","hobby":"羽毛球、乒乓球、足球、篮球"} {"index":{"_index":"itcast","_type":"person"}} {"name":"王五","age": 22,"mail": "333@qq.com","hobby":"羽毛球、篮球、游泳、听音乐"} {"index":{"_index":"itcast","_type":"person"}} {"name":"赵六","age": 23,"mail": "444@qq.com","hobby":"跑步、游泳"} {"index":{"_index":"itcast","_type":"person"}} {"name":"孙七","age": 24,"mail": "555@qq.com","hobby":"听音乐、看电影"}
测试搜索:
POST 127.0.0.1:9200/itcast/person/_search { "query":{ "match":{ "hobby":"音乐" } } }
3.7、结构化查询
3.7.1、term查询
term 主要用于精确匹配哪些值,比如数字,日期,布尔值或 not_analyzed 的字符串(未经分析的文本数据类型):
{ "term": { "age": 26 }} { "term": { "date": "2014-09-01" }} { "term": { "public": true }} { "term": { "tag": "full_text" }} #示例 POST 127.0.0.1:9200/itcast/person/_search { "query":{ "term":{ "age":20 } } }
3.7.2、terms查询
terms 跟 term 有点类似,但 terms 允许指定多个匹配条件。 如果某个字段指定了多个值,那么文档需要一起去做匹配:
POST 127.0.0.1:9200/itcast/person/_search { "query":{ "terms":{ "age" : [20,21] } } }
3.7.3、range查询
range 过滤允许我们按照指定范围查找一批数据:
范围操作符包含:
gt :: 大于
gte :: 大于等于
lt :: 小于
lte :: 小于等于
示例
POST 127.0.0.1:9200/itcast/person/_search { "query":{ "range":{ "age":{ "gte":20, "lte":22 } } } }
3.7.4、exists 查询
exists 查询可以用于查找文档中是否包含指定字段或没有某个字段,类似于SQL语句中的 IS_NULL 条件
POST 127.0.0.1:9200/itcast/person/_search { "query":{ "exists":{ "field": "hobby" } } }
3.6.5、match查询
match 查询是一个标准查询,不管你需要全文本查询还是精确查询基本上都要用到它。
如果你使用 match 查询一个全文本字段,它会在真正查询之前用分析器先分析 match 一下查询字符:
如果用 match 下指定了一个确切值,在遇到数字,日期,布尔值或者 not_analyzed 的字符串时,它将为你搜索你
给定的值:
{ "match": { "age": 26 }} { "match": { "date": "2014-09-01" }} { "match": { "public": true }} { "match": { "tag": "full_text" }}
3.7.6、bool查询
- bool 查询可以用来合并多个条件查询结果的布尔逻辑,它包含一下操作符:
- must :: 多个查询条件的完全匹配,相当于 and 。
- must_not :: 多个查询条件的相反匹配,相当于 not 。
- should :: 至少有一个查询条件匹配, 相当于 or 。
这些参数可以分别继承一个查询条件或者一个查询条件的数组:
POST 127.0.0.1:9200/itcast/person/_search { "query":{ "bool":{ "must":{ "match":{"hobby":"足球"} }, "must_not":{ "match":{"hobby":"音乐"} }, "should":[ { "match":{ "hobby":"足球" } }, { "match":{ "hobby":"羽毛球" } } ] } } }
3.8、过滤查询
前面讲过结构化查询,Elasticsearch也支持过滤查询,如term、range、match等。
示例:查询年龄为20岁的用户。
POST 127.0.0.1:9200/itcast/person/_search { "query":{ "bool":{ "filter":{ "term":{ "age":20 } } } } }
查询和过滤的对比
* 一条过滤语句会询问每个文档的字段值是否包含着特定值。
* 查询语句会询问每个文档的字段值与特定值的匹配程度如何。
一条查询语句会计算每个文档与查询语句的相关性,会给出一个相关性评分 _score,并且 按照相关性对匹配到的文档进行排序。 这种评分方式非常适用于一个没有完全配置结果的全文本搜索。
* 一个简单的文档列表,快速匹配运算并存入内存是十分方便的, 每个文档仅需要1个字节。这些缓存的过滤结果
集与后续请求的结合使用是非常高效的。
* 查询语句不仅要查找相匹配的文档,还需要计算每个文档的相关性,所以一般来说查询语句要比 过滤语句更耗时,并且查询结果也不可缓存。
建议:
做精确匹配搜索时,最好用过滤语句,因为过滤语句可以缓存数据。
配套软件和教程下载
点击下载
链接:https://pan.baidu.com/s/1HJbA3Wsgbuqyd8pX4g7cpA
提取码:e506