ELK基础
ELK是用于**数据抽取(Logstash)、搜索分析(Elasticsearch)、数据展现(Kibana)**的一整套解决方案,所以也称作ELK stack。
Elastic Stack简介
包含三大基础组件,分别是Elasticsearch、Logstash、Kibana。但实际上ELK不仅仅适用于日志分析,它还可以支持其它任何数据搜索、分析和收集的场景,日志分析和收集只是更具有代表性
组件介绍
Elasticsearch
Elasticsearch 是使用java开发,基于Lucene、分布式、通过Restful方式进行交互的近实时搜索平台框架。它的特点有:分布式,零配置,自动发现,索引自动分片,索引副本机制,restful风格接口,多数据源,自动搜索负载等。
Logstash
Logstash 基于java开发,是一个数据抽取转化工具。一般工作方式为c/s架构,client端安装在需要收集信息的主机上,server端负责将收到的各节点日志进行过滤、修改等操作在一并发往elasticsearch或其他组件上去。
Kibana
Kibana 基于nodejs,也是一个开源和免费的可视化工具。Kibana可以为 Logstash 和 ElasticSearch 提供的日志分析友好的 Web 界面,可以汇总、分析和搜索重要数据日志。
Beats
Beats 平台集合了多种单一用途数据采集器。它们从成百上千或成千上万台机器和系统向 Logstash 或 Elasticsearch 发送数据。
Beats由如下组成:
Packetbeat:轻量型网络数据采集器,用于深挖网线上传输的数据,了解应用程序动态。Packetbeat 是一款轻量型网络数据包分析器,能够将数据发送至 Logstash 或 Elasticsearch。其支 持ICMP (v4 and v6)、DNS、HTTP、Mysql、PostgreSQL、Redis、MongoDB、Memcache等协议。
Filebeat:轻量型日志采集器。当您要面对成百上千、甚至成千上万的服务器、虚拟机和容器生成的日志时,请告别 SSH 吧。Filebeat 将为您提供一种轻量型方法,用于转发和汇总日志与文件,让简单的事情不再繁杂。
Metricbeat :轻量型指标采集器。Metricbeat 能够以一种轻量型的方式,输送各种系统和服务统计数据,从 CPU 到内存,从 Redis 到 Nginx,不一而足。可定期获取外部系统的监控指标信息,其可以监控、收集 Apache http、HAProxy、MongoDB、MySQL、Nginx、PostgreSQL、Redis、System、Zookeeper等服务。
Winlogbeat:轻量型 Windows 事件日志采集器。用于密切监控基于 Windows 的基础设施上发生的事件。Winlogbeat 能够以一种轻量型的方式,将 Windows 事件日志实时地流式传输至 Elasticsearch 和 Logstash。
Auditbeat:轻量型审计日志采集器。收集您 Linux 审计框架的数据,监控文件完整性。Auditbeat 实时采集这些事件,然后发送到 Elastic Stack 其他部分做进一步分析。
Heartbeat:面向运行状态监测的轻量型采集器。通过主动探测来监测服务的可用性。通过给定 URL 列表,Heartbeat 仅仅询问:网站运行正常吗?Heartbeat 会将此信息和响应时间发送至 Elastic 的其他部分,以进行进一步分析。
Functionbeat:面向云端数据的无服务器采集器。在作为一项功能部署在云服务提供商的功能即服务 (FaaS) 平台上后,Functionbeat 即能收集、传送并监测来自您的云服务的相关数据。
Elastic cloud
基于 Elasticsearch 的软件即服务(SaaS)解决方案。通过 Elastic 的官方合作伙伴使用托管的 Elasticsearch 服务。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PfwsB98P-1681790775731)(null)]****
#一、搜索是什么
概念:用户输入想要的关键词,返回含有该关键词的所有信息。
场景:
1互联网搜索:谷歌、百度、各种新闻首页
2 站内搜索(垂直搜索):企业OA查询订单、人员、部门,电商网站内部搜索商品(淘宝、京东)场景。
#二、数据库做搜索弊端
#1、站内搜索(垂直搜索):数据量小,简单搜索,可以使用数据库。
问题出现:
l 存储问题。电商网站商品上亿条时,涉及到单表数据过大必须拆分表,数据库磁盘占用过大必须分库(mycat)。
l 性能问题:解决上面问题后,查询“笔记本电脑”等关键词时,上亿条数据的商品名字段逐行扫描,性能跟不上。
l 不能分词。如搜索“笔记本电脑”,只能搜索完全和关键词一样的数据,那么数据量小时,搜索“笔记电脑”,“电脑”数据要不要给用户。
#2、互联网搜索,肯定不会使用数据库搜索。数据量太大。PB级。
三、全文检索、倒排索引和Lucene
#1、全文检索
倒排索引表:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UoQftQSp-1681790773230)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221223210601630.png)]
如上:select * from product_term like ‘’%哪吒%‘’:
查含有哪吒的字的数据时会产生下面一个分词表(倒排索引表):
查哪吒会将有哪吒字段记入表中的分词term,含有哪吒的对应数据的id计入表中的id。如上上面四个都有,那么九江他们的content,id计入分词表对应的term和id:
分词term:哪吒,ids:1
此时查到还有其他的数据也拥有哪吒字段:哪吒海报,哪吒公仔,哪吒玩偶,对应的id2,3,4,全部计入分词表中:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yMxRiBXs-1681790773231)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221223212213100.png)]
记入的id1,2,3,4对应的除了哪吒外,还有电影,海报,公仔,玩偶,于是将它们记入term:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bd5ngMJt-1681790773231)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221223210656825.png)]
最后形成的表为倒排索引表,里面的term,id是倒排索引,进行全文检索:
select * from product_term where term = ‘哪吒’
查询等于哪吒的数据时,从分词表中知道对应的id1,2,3,4都符合,查出来返回给母表。母表根据id拿到所有与哪吒相关的数据。
这样解决了数据磁盘占用过大(将一个数据特别大的表,通过倒排索引拆分成一个精简的表,通过匹配度高的词进行全文检索),性能损耗过大,效率低的问题以及不能分词:用户搜索如搜索“笔记电脑”,“电脑”的数据也会给用户。
2 . Lucene:
就是一个jar包,里面封装了全文检索的引擎、搜索的算法代码。开发时,引入lucene的jar包,通过api开发搜索相关业务。底层会在磁盘建立索引库。
第一章 Elasticsearch(Es)是什么
简介
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pG7rB9WO-1681790776508)(null)]
官网:https://www.elastic.co/cn/products/elasticsearch
1 . 为什么使用Es?没有Es存在的问题:
数据如何分布?
已知我们单个服务器(lucene实列)只能存1t数据,java客户端连接后拿到服务器lucene的jar包后执行相关业务。如果我们此时有2t数据,那么就需要两台服务器来存储,那么数据如何分布到两台服务器呢?平分取模?可如果后续一直增加数据,那么还是这么操作吗?况且lucene也不支持这种操作,这种操作只能让java客户端来操作。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o21X9QP4-1681790773231)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221223213751440.png)]
数据如何交互?
就算成功平分数据,那么用户搜索数据在第一个服务器没找到,那么去第二个服务器找到数据了,怎么反馈呢?
数据如何备份?
数据量大时,数据如何备份?再起一个服务器(lucene实列)来进行数据保存,怎么进行数据的实时保存?
上述的三种问题,Es都可解决:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oTGq3TbT-1681790773232)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221223215249599.png)]
Es数据分布进行分片机制来解决。将所有的数据进行分片到很多个实列(shard)当中。
Es使用平行节点解决数据交互问题:客户端访问数据时,都可以平行交互到其他实列服务器的数据(访问一个服务器相当于同时访问了所有的服务器实列)。
Es使用副本机制来进行数据的保存,备份。
Es还拥有高级搜索功能(比如:分组,聚合)。
2 . Elasticsearch的功能
- 分布式的搜索引擎和数据分析引擎
搜索:互联网搜索、电商网站站内搜索、OA系统查询
数据分析:电商网站查询近一周哪些品类的图书销售前十;新闻网站,最近3天阅读量最高的十个关键词,舆情分析。
- 全文检索,结构化检索,数据分析
全文检索:搜索商品名称包含java的图书select * from books where book_name like “%java%”。
结构化检索:搜索商品分类为spring的图书都有哪些,select * from books where category_id=‘spring’
数据分析:分析每一个分类下有多少种图书,select category_id,count(*) from books group by category_id
- 对海量数据进行近实时的处理
分布式:ES自动可以将海量数据分散到多台服务器上去存储和检索,经行并行查询,提高搜索效率。相对的,Lucene是单机应用。
近实时:数据库上亿条数据查询,搜索一次耗时几个小时,是批处理(batch-processing)。而es只需秒级即可查询海量数据,所以叫近实时。秒级
3 . Es核心概念:
(1)NRT(Near Realtime):近实时
两方面:
- 写入数据时,过1秒才会被搜索到,因为内部在分词、录入索引。
- es搜索时:搜索和分析数据需要秒级出结果。
#(2)Cluster:集群
包含一个或多个启动着es实例的机器群。通常一台机器起一个es实例。同一网络下,集群名一样的多个es实例自动组成集群,自动均衡分片等行为。默认集群名为“elasticsearch”。
#(3)Node:节点
每个es实例称为一个节点。节点名自动分配,也可以手动配置。一个节点有多个主分片和副本
#(4)Index:索引
包含一堆有相似结构的文档数据。
索引创建规则:
- 仅限小写字母
- 不能包含\、/、 *、?、"、<、>、|、#以及空格符等特殊符号
- 从7.0版本开始不再包含冒号
- 不能以-、_或+开头
- 不能超过255个字节(注意它是字节,因此多字节字符将计入255个限制)
#(5)Document:文档
es中的最小数据单元。一个document就像数据库中的一条记录。通常以json格式显示。多个document存储于一个索引(Index)中。
book document
{
"book_id": "1",
"book_name": "java编程思想",
"book_desc": "从Java的基础语法到最高级特性(深入的[面向对象](https://baike.baidu.com/item/面向对象)概念、多线程、自动项目构建、单元测试和调试等),本书都能逐步指导你轻松掌握。",
"category_id": "2",
"category_name": "java"
}
#(6)Field:字段
就像数据库中的列(Columns),定义每个document应该有的字段。
#(7)Type:类型
每个索引里都可以有一个或多个type,type是index中的一个逻辑数据分类,一个type下的document,都有相同的field。
注意:6.0之前的版本有type(类型)概念,type相当于关系数据库的表,ES官方将在ES9.0版本中彻底删除type。本教程typy都为_doc。
#(8)shard:分片
index数据过大时,将index里面的数据,分为多个shard,分布式的存储在各个服务器上面。可以支持海量数据和高并发,提升性能和吞吐量,充分利用多台机器的cpu。
#(9)replica:副本
在分布式环境下,任何一台机器都会随时宕机,如果宕机,index的一个分片没有,导致此index不能搜索。所以,为了保证数据的安全,我们会将每个index的分片经行备份,存储在另外的机器上。保证少数机器宕机es集群仍可以搜索。
能正常提供查询和插入的分片我们叫做主分片(primary shard),其余的我们就管他们叫做备份的分片(replica shard)。
es6默认新建索引时,5分片,2副本,也就是一主一备,共10个分片。所以,es集群最小规模为两台
4 .Es的优点:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OGnBxiVy-1681790773232)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221223224309040.png)]
假设我们有个叫book的索引,该索引有3t的数据量。每个主分片对应有一个副本R0,1,2。
(1)我们的es集群每个实列服务器只能存1t数据。所有会分片成p0,p1,p2三个shard来存储数据。这样减轻了单个node(节点:es实列)的压力.
(2)因为每个机器的的吞吐量为1000/s,那么有三个机器,当有客户端要往里面存数据时,同时往3个里存,那么总速度就达到了3000/s,充分利用机器的性能。
(3)当数据量越来越大,那么其中的索引就会越来越多,就会分片更多的服务器实列分担压力。新增的分片会将得到其他的机器存的数据和索引信息。这样分担存储数据减轻压力,而分担索引信息更是提高了集群扩展。
(4)大数据高并发的情况下,提供副本机制提供容错(副本和主分片的数据是完全一致的)。
(5)高可用:当其中一个node宕机后,它的副本会立刻接替该node,并和其他的node建立新的索引联系。
(6)能正常提供查询和插入的分片我们叫做主分片(primary shard),其余的我们就管他们叫做备份的分片(副本)。只进行查询数据不进行增删改的情况下,那么也可以去副本查拿到结果,那么三台机器三个副本,也就意味着查询的效率达到6000/s,更加提高了吞吐量。
5 . elasticsearch核心概念 vs. 数据库核心概念
关系型数据库(比如Mysql) | 非关系型数据库(Elasticsearch) |
---|---|
数据库Database | 索引Index |
表Table | 索引Index(原为Type) |
数据行Row | 文档Document |
数据列Column | 字段Field |
约束 Schema | 映射Mapping |
6 . es相关配置:
安装es前,安装设置jdk1.8以上版本,随后在config下的elstaticsearch.yml进行配置:(es中默认端口为9200)
node.name: node-1
cluster.initial_master_nodes: ["node-1"]
xpack.ml.enabled: false
http.cors.enabled: true
http.cors.allow-origin: /.*/
在jvm.options内设置:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q5dBpH89-1681790773232)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221224130627627.png)]
随后bin下双击elstaticsearch.bat运行,运行成功后,es中默认端口为9200,浏览器输入localhost:9200或
http://localhost:9200/?pretty 查看状态:
显示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VbexjtAi-1681790773232)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221224130752327.png)]
http://localhost:9200/_cluster/health 查询集群状态:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mJazEiXu-1681790773233)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221224133737195.png)]
Status:集群状态。Green 所有分片可用。Yellow所有主分片可用。Red主分片不可用,集群不可用。
7 . Kibana相关配置:
在Kibana.yml配置 修改为支持中文:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VYpTn8af-1681790773233)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221224135356368.png)]
随后在bin下启动Kibana.bat(Kibana的默认端口为5601)
浏览器访问http://localhost:5601 进入Dev Tools界面:
5、发送get请求,查看集群状态GET _cluster/health。相当于浏览器访问。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KpLEGx7J-1681790776931)(null)]
总览
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cyrQOL2n-1681790777109)(null)]
Dev Tools界面
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PHe30wRK-1681790777203)(null)]
监控集群界面
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c4wo3wC8-1681790777378)(null)]
集群状态(搜索速率、索引速率等
8 .Elstaticsearch-head插件安装:
安装后,在该文件目录下打开黑窗口,运行npm run start 显示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R0xBijh4-1681790773234)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221224174344211.png)]
在浏览器输入请求:http://localhost:9100显示出Elstaticsearch-head插件页面:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Kk8LB1gU-1681790773234)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221224175100296.png)]
已知我们启动了Es,Es-head插件它自动连接到Es默认iphttp://localhost:9200,我们点击连接http://localhost:9200后显示出了Es的内容:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CaELpz5j-1681790773234)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221224175113861.png)]
第二章 Es 快速入门
1 . 文档的数据格式:
(1)应用系统的数据结构都是面向对象的,具有复杂的数据结构
(2)对象存储到数据库,需要将关联的复杂对象属性插到另一张表,查询时再拼接起来。
(3)es面向文档,文档中存储的数据结构,与对象一致。所以一个对象可以直接存成一个文档。
(4)es的document用json数据格式来表达。
例如我们在java中一个使用类来对一个目标封装,比如班级类对应学生,姓名,年龄等属性,es通过json字符串形式来进行存储
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qsKXTGwo-1681790773235)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221224180207849.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CEfBq6uV-1681790773235)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221224180219819.png)]
2 . 简单的集群管理:
(1)快速检查集群的健康状况
打开kibana,开发工具:查看es健康状况
输入:GET /_cat/health?v (加个?v表示把每个数据对应属于哪个表的那哪个列的信息也显示打印出来)
随后在右侧显示出对应状况的数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Qck8QG2W-1681790773235)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221224181804246.png)]
如果只是::GET /_cat/health
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UN0nxjRS-1681790773235)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221224182604537.png)]
如何快速了解集群的健康状况?green、yellow、red?
green:每个索引的primary shard(主分片)和replica shard(副本)都是active状态的
yellow:每个索引的primary shard(主分片)都是active状态的,但是部分replica shard(副本)不是active状态,处于不可用的状态
red:不是所有索引的primary shard都是active状态的,部分索引有数据丢失
(2)快速查看集群中的索引:
GET /_cat/indices?v
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S0dM9BsX-1681790773235)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221224182530888.png)]
(3)简单的索引操作:
注意:创建索引时,不同数据放到不同索引中:
如下图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-899WJfsc-1681790773236)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221224194239857.png)]
如果把user和order索引都全放到下面三个分片中,把数据混杂起来,业务人员要对订单order索引进行分析,有的分片内既存有order的索引,还存有user的索引,那么势必会对搜索分析过程造成干扰。
如果在某些时候突然order数据暴增,order的读写非常繁忙,而user和order的放在一块的话,势必会影响导致user的读写操作变慢,同时user本身速度也会因为user的读写变慢。
创建索引:
PUT /demo_index?pretty (pretty表示用json格式)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vT6GqCqg-1681790773236)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221224182846151.png)]
acknowledged为true:表示主分片接收到了创建索引的请求
shards_acknowledged为true:表示副本接收到了创建索引的请求
最后成功创建索引,名字叫demo_index的索引
删除索引:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FzsnLBND-1681790773236)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221224183127020.png)]
acknowledged为true:表示主分片接收到了删除索引的请求,成功删除了叫demo_index的索引
3 . 商品的CRUD操作
先创建一个图书的索引:
PUT /book
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FJ57kr4W-1681790773236)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221224183534907.png)]
(1)插入数据:语法:PUT /index/type/id
往book索引里插入一条数据:该数据id为1,文本类型
PUT /book/_doc/1
PUT /book/_doc/1
{
"name": "Bootstrap开发",
"description": "Bootstrap是由Twitter推出的一个前台页面开发css框架,是一个非常流行的开发框架,此框架集成了多种页面效果。此开发框架包含了大量的CSS、JS程序代码,可以帮助开发者(尤其是不擅长css页面开发的程序人员)轻松的实现一个css,不受浏览器限制的精美界面css效果。",
"studymodel": "201002",
"price":38.6,
"timestamp":"2019-08-25 19:11:35",
"pic":"group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg",
"tags": [ "bootstrap", "dev"]
}
运行显示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RSYRYWAN-1681790773236)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221224183852906.png)]
同理插入id为2,3的图书信息:
PUT /book/_doc/2
{
"name": "java编程思想",
"description": "java语言是世界第一编程语言,在软件开发领域使用人数最多。",
"studymodel": "201001",
"price":68.6,
"timestamp":"2019-08-25 19:11:35",
"pic":"group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg",
"tags": [ "java", "dev"]
}
PUT /book/_doc/3
{
"name": "spring开发基础",
"description": "spring 在java领域非常流行,java程序员都在用。",
"studymodel": "201001",
"price":88.6,
"timestamp":"2019-08-24 19:11:35",
"pic":"group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg",
"tags": [ "spring", "java"]
}
(2)查询数据:语法:GET /index/type/id
查询图书,检索文档:
查询book中id为1,类型为文本_doc的信息
GET /book_doc/1
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-coRqRiRH-1681790773236)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221224184245115.png)]
我们可以打开kibana的discovery,快速索引,将book输入,它就会自动检索到我们创建book索引,拿到book索引的所有数据显示出来:方便我们查看整个book的数据,如果只想查看到id,价格,书名等信息,点击左边的对应可用字段即可
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FChl1wcV-1681790773237)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221224184819683.png)]
如只看id和索引:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8j70pJj9-1681790773237)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221224185138580.png)]
(3)修改:全局替换操作
PUT /book/_doc/1
{
"name": "Bootstrap开发教程1",
"description": "Bootstrap是由Twitter推出的一个前台页面开发css框架,是一个非常流行的开发框架,此框架集成了多种页面效果。此开发框架包含了大量的CSS、JS程序代码,可以帮助开发者(尤其是不擅长css页面开发的程序人员)轻松的实现一个css,不受浏览器限制的精美界面css效果。",
"studymodel": "201002",
"price":38.6,
"timestamp":"2019-08-25 19:11:35",
"pic":"group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg",
"tags": [ "bootstrap", "开发"]
}
可以看到,运行后对result显示了更新内容:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OF4ii6OY-1681790773237)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221224190612748.png)]
但是这个是全局替换,需要带上所有的信息才能替换
(4)修改:局部替换:
语法:POST /{index}/type /{id}/_update
我们要修改文档中,且只修改name这一个属性的内容:
POST /book/_doc/1/_update
因为_doc马上要被系统删除不用了,所以使用下面的格式:
POST /book/_doc/1/_update
{
"doc": {
"name": " Bootstrap开发教程高级666"
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ywGSgys4-1681790773237)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221224191308982.png)]
查询时发现确实修改成功:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A70a5clL-1681790773237)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221224191453783.png)]
(5)删除:
删除id为1的文档数据
DELETE /book/_doc/1
4 . 生成文档id:
(1)手动生成id
场景:数据从其他系统导入时,本身有唯一主键。如数据库中的图书、员工信息等。
用法:put /index/_doc/id
PUT /test_index/_doc/1
{
"test_field": "test"
}
(2)自动生成id(id自动递增):
用法:POST /index/_doc
POST /test_index/_doc
{
"test_field": "test1"
}
如下,es自动生成了id的串儿:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dFkULEfw-1681790773237)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221224194814838.png)]
5 . _source 字段:
含义:插入数据时的所有字段和值。在get获取数据时,在_source字段中原样返回。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BnEy4tRw-1681790773238)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221224200333053.png)]
(1)定制指定返回字段:
source_includes:表示要拿指定的字段的信息
只查看价格和名字:
GET /book/_doc/1?_source_includes=price,name
source只显示了介个和name的信息:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h9PM8eML-1681790773238)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221224200805770.png)]
6 . 文档的替换和删除:
(1)全量替换:
PUT /test_index/_doc/1
{
"test_field": "test"
}
执行语句新增数据后,会后一个version为1,再执行该语句,version为2,执行两次,返回结果中版本号(_version)在不断上升。此过程为全量替换。先前的数据为一个待删除的数据,实质:旧文档的内容不会立即删除,只是标记为deleted。适当的时机,集群会将这些文档删除。
(2)强制创建:
为防止覆盖原有数据,我们在新增时,设置为强制创建,不会覆盖原有文档。
语法:PUT /index/ _doc/id/__create
新增id为4的数据:
PUT /book/_doc/4/_create
{
"name": "Bootstrap开发教程1",
"description": "Bootstrap是由Twitter推出的一个前台页面开发css框架,是一个非常流行的开发框架,此框架集成了多种页面效果。此开发框架包含了大量的CSS、JS程序代码,可以帮助开发者(尤其是不擅长css页面开发的程序人员)轻松的实现一个css,不受浏览器限制的精美界面css效果。",
"studymodel": "201002",
"price":38.6,
"timestamp":"2019-08-25 19:11:35",
"pic":"group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg",
"tags": [ "bootstrap", "开发"]
}
执行后,我们再执行该语句报错说该数据已经存在,不能覆盖,不能重复。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GpsPhZJj-1681790773238)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221224203430384.png)]
(3)删除:(延迟删除)
DELETE /book/id
DELETE /book/_doc/id
DELETE /book/_doc/1/
实质:旧文档的内容不会立即删除,只是标记为deleted。适当的时机,集群会将这些文档删除。
7 . 局部更新(局部替换):
使用 PUT /index/type/id 为文档全量替换,需要将文档所有数据提交。
partial update局部替换则只修改变动字段。
用法:
post /index/type/id/_update
{
"doc": {
"field":"value"
}
}
内部与全量替换是一样的,旧文档标记为删除,新建一个文档。
优点:
- 大大减少网络传输次数和流量,提升性能
- 减少并发冲突发生的概率。
7 . 批量增删改:
批量增语法:POST /_bulk
其他的以此类推。
POST /_bulk
{"action": {"metadata"}}
{"data"}
8 . 使用脚本更新:
es可以内置脚本执行复杂操作
(1)内置脚本:
修改文档6的num字段,+1。
插入数据
PUT /test_index/_doc/6
{
"num": 0,
}
执行脚本操作(ctx:上下文,_source:文档6的source中的内容num+1)
POST /test_index/_doc/6/_update
{
"script" : "ctx._source.num+=1"
}
搜索所有文档,将num字段乘以2输出
插入数据
PUT /test_index/_doc/7
{
"num": 5
}
查询
GET /test_index/_search
{
"script_fields": {
"my_doubled_field": {
"script": {
"lang": "expression",
"source": "doc['num'] * multiplier",
"params": {
"multiplier": 2
}
}
}
}
}
返回
{
"_index" : "test_index",
"_type" : "_doc",
"_id" : "7",
"_score" : 1.0,
"fields" : {
"my_doubled_field" : [
10.0
]
}
}
9 . 图解es的并发问题
如同商品秒杀,多线程情况下,es同样会出现并发冲突问题
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i1lUNFI7-1681790773238)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221224213124651.png)]
10 . 图解悲观锁与乐观锁机制
解决es并发问题:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9tcyq1AC-1681790773238)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221224221026145.png)]
11 . java 客户端 获取es简单数据
我们启动es,kebana后
(1)高层api:
导入以来:
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.3.0</version>
<exclusions>
<exclusion>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.3.0</version>
</dependency>
java代码:
public class TestDemo {
public static void main(String[] args) throws IOException {
//连接es的步骤:
//1.获取连接的客户端
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost",9200,"http")));
//2.构建请求,查询索引book的id为1的数据
GetRequest getRequest = new GetRequest("book","1");
//3.执行,这里请求参数使用默认
GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
//4.拿到响应后解析,查询到数据后获取结果打印输出显示
System.out.println(getResponse.getId());
System.out.println(getResponse.getVersion());
System.out.println(getResponse.getSource());
}
}
输出显示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rlFqfFvw-1681790773238)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221225102214406.png)]
12 . 结合springboot获取es数据查询操作:
- 当今趋势
- 方便开发
- 创建连接交由spring容器,避免每次请求的网络开销。
引入依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<version>2.0.6.RELEASE</version>
</dependency>
配置springboot配置文件:
spring:
application:
name: service-search
heima:
elasticsearch:
hostlist: 127.0.0.1:9200 #多个结点中间用逗号分隔
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bpkjONyg-1681790773239)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221225102727072.png)]
设置主启动类:
@SpringBootApplication
public class SearchApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SearchApplication.class, args);
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bsiWRagO-1681790773239)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221225102949502.png)]
springboot搭建完成后,我们只需要将我们前面的高级es获取数据的类注入springboot容器内,我们的springboot就可以拿来使用了:
已知我们在kibana插入了这个数据:
PUT /test_post/_doc/1
{
"user":"tom",
"postDate":"2019-07-18",
"message":"trying out es"
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JyOTcqgy-1681790773239)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221225111035398.png)]
我们先配置springboot配置类:
@Configuration
public class ElestaticSearchConfig {
@Value("${heima.elasticsearch.hostlist}")
private String hostlist;
@Bean(destroyMethod = "close")// RestClient用完后需要关闭,close是RestClient自带的关闭方法
public RestHighLevelClient getRestHighLevelClient(){
//按照逗号分割,因为可能会写有多个ip,拿出每个ip
String[] split = hostlist.split(",");
//定义一个数组将split存入该数组操作
HttpHost[] httpHostArray = new HttpHost[split.length];
for (int i = 0; i < split.length; i++) {
String item = split[i];
//将拿到的ip,端口分隔开存入httpArray数组
httpHostArray[i] = new HttpHost(item.split(":")[0],
Integer.parseInt(item.split(":")[1]),"http");
}
//将数组传入实现对es的连接
return new RestHighLevelClient(RestClient.builder(httpHostArray));
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZMdJG3EZ-1681790773239)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221225112911258.png)]
随后测试类测试查询test_post中的id为1的几个数据:
@SpringBootTest(classes =SearchApplication.class)
@RunWith(SpringRunner.class)
public class TestDocument {
@Autowired
RestHighLevelClient client;
@Test
public void test1() throws IOException {
//1.连接请求
GetRequest getRequest = new GetRequest("test_post","1");
//执行
GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
System.out.println(getResponse.getId());
System.out.println(getResponse.getVersion());
System.out.println(getResponse.getSource());
}
}
运行后:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6rHtH1TV-1681790773239)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221225113047952.png)]
(1)输出可选参数:
在构建请求时,设置请求我们想要的参数
@SpringBootTest(classes =SearchApplication.class)
@RunWith(SpringRunner.class)
public class TestDocument {
@Autowired
RestHighLevelClient client;
@Test
public void test1() throws IOException {
//1.连接请求
GetRequest getRequest = new GetRequest("test_post","1");
//设置不想要的字段为user,message字段的,
String[] includes =Strings.EMPTY_ARRAY;
String[] excludes = new String[]{
"user","message"};
FetchSourceContext fetchSourceContext = new FetchSourceContext(true, includes, excludes);
GetRequest getRequest1 = getRequest.fetchSourceContext(fetchSourceContext);
//执行
GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
System.out.println(getResponse.getId());
System.out.println(getResponse.getVersion());
System.out.println(getResponse.getSource());
}
}
运行后,source中只打印输出了postDate字段的数据:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CVjMWbCl-1681790773239)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221225120911370.png)]
上述的操作都是同步查询:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ahgoDkW8-1681790773240)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221225121750622.png)]
(2)异步查询:
@SpringBootTest(classes =SearchApplication.class)
@RunWith(SpringRunner.class)
public class TestDocument {
@Autowired
RestHighLevelClient client;
@Test
public void test1() throws IOException {
//1.连接请求
GetRequest getRequest = new GetRequest("test_post","1");
String[] includes =Strings.EMPTY_ARRAY;
String[] excludes = new String[]{
"user","message"};
FetchSourceContext fetchSourceContext = new FetchSourceContext(true, includes, excludes);
GetRequest getRequest1 = getRequest.fetchSourceContext(fetchSourceContext);
//执行
//同步查询
// GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
//异步查询:
//创建一个监听器:监听发送异步请求查询是否能成功
ActionListener<GetResponse> listener = new ActionListener<GetResponse>() {
//请求成功时执行
@Override
public void onResponse(GetResponse getResponse) {
System.out.println(getResponse.getId());
System.out.println(getResponse.getVersion());
System.out.println(getResponse.getSource());
}
//失败时执行:
@Override
public void onFailure(Exception e) {
e.printStackTrace();
}
};
client.getAsync(getRequest,RequestOptions.DEFAULT,listener);
//由于我们在注解上设置客户端在发送请求后会立刻关闭client:@Bean(destroyMethod = "close")/
//所以我们需要让主线程睡一会儿,防止测试时无法访问
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
运行后:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-65Sw5U2k-1681790773240)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221225132245022.png)]
我们可以获取结果时以 好几种方式来拿到结果,按照需求来给定结果:
// 获取结果
if (getResponse.isExists()) {
long version = getResponse.getVersion();
String sourceAsString = getResponse.getSourceAsString();//检索文档(String形式)
System.out.println(sourceAsString);
byte[] sourceAsBytes = getResponse.getSourceAsBytes();//以字节接受
Map<String, Object> sourceAsMap = getResponse.getSourceAsMap();
System.out.println(sourceAsMap);
}else {
}
13 . springboot进行文档新增数据操作
@Autowired
RestHighLevelClient client;
@Test
public void testAdd() throws IOException {
//1.构建请求
// PUT /test_post/_doc/2
//构建请求头:
IndexRequest request = new IndexRequest("test_post");
request.id("3");
//构建请求体:四种方法
//方法一:
String jsonString = "{\n" +
" \"user\":\"tom\",\n" +
" \"postDate\":\"2019-07-18\",\n" +
" \"message\":\"trying out es\"\n" +
"}\n";
request.source(jsonString, XContentType.JSON);//插入的字符串是json
// //方法二:
// Map<String, Object> jsonMap = new HashMap<>();
// jsonMap.put("user","tom");
// jsonMap.put("postDate","2019-07-18");
// jsonMap.put("message","trying out es");
// request.source(jsonMap);
// //方法三:
// XContentBuilder builder = XContentFactory.jsonBuilder();
// builder.startObject();
// {
// builder.field("user","tom");
// builder.field("postDate","2019-07-18");
// builder.field("message","trying out es");
// }
// builder.endObject();
// request.source(builder);
// //方法四:
// request.source("user","tom",
// "postDate","2019-07-18",
// "message","trying out es");
//可选参数:
//设置超时时间1s,下面两种都一样:
request.timeout("1s");
request.timeout(TimeValue.timeValueSeconds(1));
//手动维护版本号:
request.version(2);
request.versionType(VersionType.EXTERNAL);
//2.执行
IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);
//3.获取结果
System.out.println(indexResponse.getIndex());
System.out.println(indexResponse.getId());
System.out.println(indexResponse.getResult());
//test_post
//3
//CREATED
}
我们查询时可以同步,异步操作,同理新增数据也会有这些操作,同步操作:上述操作
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pCpxNxQL-1681790773240)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221225141326642.png)]
异步操作:
//创建一个监听器:监听发送异步请求查询是否能成功
ActionListener<IndexResponse> listener = new ActionListener<IndexResponse>() {
@Override
public void onResponse(IndexResponse indexResponse) {
System.out.println(indexResponse.getIndex());
System.out.println(indexResponse.getId());
System.out.println(indexResponse.getResult());
}
@Override
public void onFailure(Exception e) {
e.printStackTrace();
}
};
//3.获取结果
client.indexAsync(request,RequestOptions.DEFAULT,listener);
//test_post
//3
//CREATED
我们这里使用同步操作,获取结果后进行一些判断:
System.out.println(indexResponse.getIndex());
System.out.println(indexResponse.getId());
System.out.println(indexResponse.getResult());
//如果这个操作是插入新增操作,就打印出来
if(indexResponse.getResult() == DocWriteResponse.Result.CREATED){
DocWriteResponse.Result result = indexResponse.getResult();
System.out.println("CREATE---"+result.toString());
//同理
}else if(indexResponse.getResult() == DocWriteResponse.Result.UPDATED){
DocWriteResponse.Result result = indexResponse.getResult();
System.out.println("update---" + result.toString());
}else{
}
运行后报错版本问题:
因为我们对数据进行了修改,数据的版本应该变化,我们设置的手动维护版本号:所以修改版本号+1:
//手动维护版本号:
request.version(3);
request.versionType(VersionType.EXTERNAL);
我们对该索引下id为3的数据的name进行修改:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LS2Q9b34-1681790773240)(C:\Users\陈刚\AppData\Roaming\Typora\typora-user-images\image-20221225150217398.png)]
显示出修改成功。
我们在java上拿到分片的信息,进行对分片的判断:
//对分片的操作:
ReplicationResponse.ShardInfo shardInfo = indexResponse.getShardInfo();
//判断成功的分片如果不等于总的主分片数
if(shardInfo.getTotal() != shardInfo.getSuccessful()){
System.out.println("处理成功的分片数少于总分片");
}
//失败的分片