文章目录

  • ElasticSearch检索
    • 1.1、初识ElasticSearch
    • 1.2、ElasticSearch基本概念
    • 1.3、ElasticSearch与kibana安装
    • 2.1整合
      • 1.导入依赖
      • 2.创建实体类
      • 3.实现ElasticsearchRepository
      • 4.测试
  • 消息
    • 1.1、前言
      • 1、任务异步处理:
      • 2、应用程序解耦合:
    • 1.2、AMQP和JMS
    • 1.3、常见MQ产品
    • 2、RabbitMQ快速入门
      • 2.1、安装
      • 2.2、springboot整合
        • 首先导入amqp的坐标
        • 配置文件配置
        • 启动类
        • 序列化配置
        • bean类
        • 监听的service
        • 测试添加消息的类
        • 控制消息队列测试
        • 控制消息队列测试

ElasticSearch检索

1.1、初识ElasticSearch

我们的应用经常需要添加检索功能,开源的 ElasticSearch 是目前全文搜索引擎的首选。他可以快速的存储、搜索和分析海量数据。Spring Boot通过整合SpringData ElasticSearch为我们提供了非常便捷的检索功能支持。

Elasticsearch是一个分布式搜索服务,提供Restful API,底层基于Lucene,采用多shard(分片)的方式保证数据安全,并且提供自动resharding的功能,github等大型的站点也是采用了ElasticSearch作为其搜索服务。

官方原话:

Elasticsearch 是一个分布式的开源搜索和分析引擎,适用于所有类型的数据,包括文本、数字、地理空间、结构化和非结构化数据。Elasticsearch 在 Apache Lucene 的基础上开发而成,由 Elasticsearch N.V.(即现在的 Elastic)于 2010 年首次发布。Elasticsearch 以其简单的 REST 风格 API、分布式特性、速度和可扩展性而闻名,是 Elastic Stack 的核心组件;Elastic Stack 是适用于数据采集、充实、存储、分析和可视化的一组开源工具。人们通常将 Elastic Stack 称为 ELK Stack(代指 Elasticsearch、Logstash 和 Kibana),目前 Elastic Stack 包括一系列丰富的轻量型数据采集代理,这些代理统称为 Beats,可用来向 Elasticsearch 发送数据。

1.2、ElasticSearch基本概念

1、Index (索引)

动词:相当于MySQL中的insert
名词:相当于MySQL中的Database
2、Type (类型)

在 Index (索引) 中,可以定义一个或多个类型,类似于MySQL中的Table,每一种类型的数据放在一起。
3、Document (文档)

保存在某个索引 (index) 下,某种类型 (Type) 的一个数据 (Document)。文档是JSON格式的,Document就像是MySQL中的某个table里面的内容。
4、概念关系图一览

5、倒排索引机制

1.3、ElasticSearch与kibana安装

为了安装方便,我们还是以容器化技术Docker进行安装:

1、下载镜像文件

[howie@laizhenghua /]$ sudo docker search elasticsearchdocker pull elasticsearch:7.4.2 # 存储和检索数据
dicker pull kibana:7.4.2 # 可视化检索数据[howie@laizhenghua /]$ sudo docker images
REPOSITORY      TAG       IMAGE ID       CREATED         SIZE
mysql           5.7       f07dfa83b528   3 weeks ago     448MB
redis           latest    ef47f3b6dc11   5 weeks ago     104MB
kibana          7.4.2     230d3ded1abc   14 months ago   1.1GB
elasticsearch   7.4.2     b1179d41a7b4   14 months ago   855MB

2、创建挂载目录

sudo mkdir -p /mydata/elasticsearch/config
sudo mkdir -p /mydata/elasticsearch/data
sudo chmod -R 777 /mydata/elasticsearch/
sudo echo "http.host: 0.0.0.0" >/mydata/elasticsearch/config/elasticsearch.yml

chmod:change mode -R(Recursion 递归)

3、启动elasticsearch

sudo docker run --name elasticsearch -p 9200:9200 -p 9300:9300 \
-e  "discovery.type=single-node" \
-e ES_JAVA_OPTS="-Xms64m -Xmx512m" \
-v /mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v /mydata/elasticsearch/data:/usr/share/elasticsearch/data \
-v  /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
-d elasticsearch:7.4.2

4、启动 kibana

sudo docker run --name kibana -e ELASTICSEARCH_HOSTS=http://https://es-0a8t6rzt.public.tencentelasticsearch.com:9200/lanlan/Article -p 5601:5601 -d kibana:7.4.2[howie@laizhenghua /]$ sudo docker run --name kibana -e ELASTICSEARCH_HOSTS=https://es-0a8t6rzt.public.tencentelasticsearch.com:9200/lanlan/Article -p 5601:5601 -d kibana:7.4.2
9b88afc2f1c00891125eeb9610bb149a023b8044bb887568219f7f160059005d

访问服务器的5601端口!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RpqstGM6-1644044896802)(C:\Users\86157\AppData\Local\Temp\1643814866889.png)]

由于我之前的阿里云服务器的内存不够,于是我申请了一个腾讯云的es。

这次我们用到的是简单的ES的整合。

2.1整合

1.导入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
2.创建实体类
@Document(indexName = "lanlan")
@Data
public class Article {@Idprivate Integer id;@Field(type = FieldType.Text)private String author;@Field(type = FieldType.Text,analyzer = "ik_max_word")private String title;
}
3.实现ElasticsearchRepository
public interface ArticleRepository extends ElasticsearchRepository<Article,Integer> {List<Article> findArticleByTitle(String title);List<Article> findByTitle(String title);List<Article> findByTitleContaining(String title);
}
4.测试
@SpringBootTest
class Demo12ElasticsearchApplicationTests {@AutowiredArticleRepository articleRepository;@Autowiredprivate ElasticsearchRestTemplate elasticsearchRestTemplate;@Testpublic void test03(){/*     Iterable<Article> all = articleRepository.findAll();for (Article article : all) {System.out.println(article);}*/List<Article> Forest = articleRepository.findByTitleContaining("森林");for (Article article : Forest) {System.out.println(article);}}@Testpublic void test02(){Article article = new Article();article.setId(3);article.setTitle("挪威森林1");article.setAuthor("村上春树");articleRepository.save(article);}}

ElasticsearchRepository中的方法名对应我在官网中找到了这样的依据,现在粘贴过来。

如表所示

关键词 样本 Elasticsearch 查询字符串
And findByNameAndPrice { "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "?", "fields" : [ "name" ] } }, { "query_string" : { "query" : "?", "fields" : [ "price" ] } } ] } }}
Or findByNameOrPrice { "query" : { "bool" : { "should" : [ { "query_string" : { "query" : "?", "fields" : [ "name" ] } }, { "query_string" : { "query" : "?", "fields" : [ "price" ] } } ] } }}
Is findByName { "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "?", "fields" : [ "name" ] } } ] } }}
Not findByNameNot { "query" : { "bool" : { "must_not" : [ { "query_string" : { "query" : "?", "fields" : [ "name" ] } } ] } }}
Between findByPriceBetween { "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : ?, "to" : ?, "include_lower" : true, "include_upper" : true } } } ] } }}
LessThan findByPriceLessThan { "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : null, "to" : ?, "include_lower" : true, "include_upper" : false } } } ] } }}
LessThanEqual findByPriceLessThanEqual { "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : null, "to" : ?, "include_lower" : true, "include_upper" : true } } } ] } }}
GreaterThan findByPriceGreaterThan { "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : ?, "to" : null, "include_lower" : false, "include_upper" : true } } } ] } }}
GreaterThanEqual findByPriceGreaterThan { "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : ?, "to" : null, "include_lower" : true, "include_upper" : true } } } ] } }}
Before findByPriceBefore { "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : null, "to" : ?, "include_lower" : true, "include_upper" : true } } } ] } }}
After findByPriceAfter { "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : ?, "to" : null, "include_lower" : true, "include_upper" : true } } } ] } }}
Like findByNameLike { "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "?*", "fields" : [ "name" ] }, "analyze_wildcard": true } ] } }}
StartingWith findByNameStartingWith { "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "?*", "fields" : [ "name" ] }, "analyze_wildcard": true } ] } }}
EndingWith findByNameEndingWith { "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "*?", "fields" : [ "name" ] }, "analyze_wildcard": true } ] } }}
Contains/Containing findByNameContaining { "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "*?*", "fields" : [ "name" ] }, "analyze_wildcard": true } ] } }}
In(当注释为 FieldType.Keyword 时) findByNameIn(Collection<String>names) { "query" : { "bool" : { "must" : [ {"bool" : {"must" : [ {"terms" : {"name" : ["?","?"]}} ] } } ] } }}
In findByNameIn(Collection<String>names) { "query": {"bool": {"must": [{"query_string":{"query": "\"?\" \"?\"", "fields": ["name"]}}]}}}
NotIn(当注释为 FieldType.Keyword 时) findByNameNotIn(Collection<String>names) { "query" : { "bool" : { "must" : [ {"bool" : {"must_not" : [ {"terms" : {"name" : ["?","?"]}} ] } } ] } }}
NotIn findByNameNotIn(Collection<String>names) {"query": {"bool": {"must": [{"query_string": {"query": "NOT(\"?\" \"?\")", "fields": ["name"]}}]}}}
True findByAvailableTrue { "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "true", "fields" : [ "available" ] } } ] } }}
False findByAvailableFalse { "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "false", "fields" : [ "available" ] } } ] } }}
OrderBy findByAvailableTrueOrderByNameDesc { "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "true", "fields" : [ "available" ] } } ] } }, "sort":[{"name":{"order":"desc"}}] }
Exists findByNameExists {"query":{"bool":{"must":[{"exists":{"field":"name"}}]}}}
IsNull findByNameIsNull {"query":{"bool":{"must_not":[{"exists":{"field":"name"}}]}}}
IsNotNull findByNameIsNotNull {"query":{"bool":{"must":[{"exists":{"field":"name"}}]}}}
IsEmpty findByNameIsEmpty {"query":{"bool":{"must":[{"bool":{"must":[{"exists":{"field":"name"}}],"must_not":[{"wildcard":{"name":{"wildcard":"*"}}}]}}]}}}
IsNotEmpty findByNameIsNotEmpty {"query":{"bool":{"must":[{"wildcard":{"name":{"wildcard":"*"}}}]}}}

消息

1.1、前言

在介绍RabbitMQ之前,我们先来看下面一个电商项目的场景:

  • 商品的原始数据保存在数据库中,增删改查都在数据库中完成。

  • 搜索服务数据来源是索引库(Elasticsearch),如果数据库商品发生变化,索引库数据不能及时更新。

  • 商品详情做了页面静态化处理,静态页面数据也不会随着数据库商品更新而变化。

如果我们在后台修改了商品的价格,搜索页面和商品详情页显示的依然是旧的价格,这样显然不对。该如何解决?

我们可能会想到这么做:

  • 方案1:每当后台对商品做增删改操作,同时修改索引库数据及更新静态页面。

  • 方案2:搜索服务和商品页面静态化服务对外提供操作接口,后台在商品增删改后,调用接口。

这两种方案都有个严重的问题:就是代码耦合,后台服务中需要嵌入搜索和商品页面服务,违背了微服务的独立原则。

这时,我们就会采用另外一种解决办法,那就是消息队列

商品服务对商品增删改以后,无需去操作索引库和静态页面,只需向MQ发送一条消息(比如包含商品id的消息),也不关心消息被谁接收。 搜索服务和静态页面服务监听MQ,接收消息,然后分别去处理索引库和静态页面(根据商品id去更新索引库和商品详情静态页面)。

什么是消息队列
MQ全称为Message Queue,即消息队列。“消息队列”是在消息的传输过程中保存消息的容器。它是典型的:生产者、消费者模型。生产者不断向消息队列中生产消息,消费者不断的从队列中获取消息。因为消息的生产和消费都是异步的,而且只关心消息的发送和接收,没有业务逻辑的侵入,这样就实现了生产者和消费者的解耦。

开发中消息队列通常有如下应用场景:

1、任务异步处理:

高并发环境下,由于来不及同步处理,请求往往会发生堵塞,比如说,大量的insert,update之类的请求同时到达MySQL,直接导致无数的行锁表锁,甚至最后请求会堆积过多,从而触发too many connections错误。通过使用消息队列,我们可以异步处理请求,从而缓解系统的压力。将不需要同步处理的并且耗时长的操作由消息队列通知消息接收方进行异步处理。减少了应用程序的响应时间。

2、应用程序解耦合:

MQ相当于一个中介,生产方通过MQ与消费方交互,它将应用程序进行解耦合。

1.2、AMQP和JMS

MQ是消息通信的模型,并发具体实现。现在实现MQ的有两种主流方式:AMQP、JMS。

两者间的区别和联系:

JMS是定义了统一的接口,来对消息操作进行统一;AMQP是通过规定协议来统一数据交互的格式

JMS限定了必须使用Java语言;AMQP只是协议,不规定实现方式,因此是跨语言的。

JMS规定了两种消息模型;而AMQP的消息模型更加丰富

1.3、常见MQ产品

  • ActiveMQ:基于JMS

  • RabbitMQ:基于AMQP协议,erlang语言开发,稳定性好

  • RocketMQ:基于JMS,阿里巴巴产品,目前交由Apache基金会-

  • Kafka:分布式消息系统,高吞吐量

2、RabbitMQ快速入门

RabbitMQ是由erlang语言开发,基于AMQP(Advanced Message Queue 高级消息队列协议)协议实现的消息队列,它是一种应用程序之间的通信方法,消息队列在分布式系统开发中应用非常广泛。RabbitMQ官方地址:http://www.rabbitmq.com

2.1、安装

安装RabbitMQ

docker pull rabbitmq

这里是直接安装最新的,如果需要安装其他版本在rabbitmq后面跟上版本号即可

启动RabbitMQ

docker run -d --hostname my-rabbit --name rabbit -p 15672:15672 -p 5672:5672 rabbitmq

这是我们的转换器

Data\Local\Temp\1644044635591.png)]

这是我们的队列

2.2、springboot整合

使用也是非常简单

首先导入amqp的坐标
<dependency><groupId>org.springframework.amqp</groupId><artifactId>spring-rabbit</artifactId><version>2.4.2</version>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency>
配置文件配置
spring:rabbitmq:host: 8.142.109.1username: guestpassword: guest
启动类
@EnableRabbit
@SpringBootApplication
public class Demo10RabbitMqApplication {public static void main(String[] args) {SpringApplication.run(Demo10RabbitMqApplication.class, args);}}
序列化配置

有了这个bean才能在消息队列中添加类

@Configuration
public class MyAMQPConfig {@Beanpublic MessageConverter messageConverter() {return new Jackson2JsonMessageConverter();}
}
bean类
@Data
public class Book {private String bookName;private String author;
}
监听的service
@Service
public class BookService {/*** 监听队列* @param book*/@RabbitListener(queues = "atguigu.news")public void receive(Book book){System.out.println("收到消息"+book);}
}
测试添加消息的类
@Test
void boottest(){Book book = new Book();book.setBookName("挪威的森林");book.setAuthor("村上春书");rabbitTemplate.convertAndSend("exchange.direct","atguigu.news",book);
}
控制消息队列测试
    @Testpublic void createEchange(){//        amqpAdmin.declareExchange(new DirectExchange("xiaolan.direct"));
//        amqpAdmin.declareQueue(new Queue("amqpadmin.queue"));amqpAdmin.declareBinding(new Binding("amqpadmin.queue",Binding.DestinationType.QUEUE,"xiaolan.direct","amqp.haha",null));System.out.println("创建完成");}
控制消息队列测试
    @Testpublic void createEchange(){//        amqpAdmin.declareExchange(new DirectExchange("xiaolan.direct"));
//        amqpAdmin.declareQueue(new Queue("amqpadmin.queue"));amqpAdmin.declareBinding(new Binding("amqpadmin.queue",Binding.DestinationType.QUEUE,"xiaolan.direct","amqp.haha",null));System.out.println("创建完成");}

springboot整合消息索引相关推荐

  1. SpringBoot整合 ActiveMQ、SpringBoot整合RabbitMQ、SpringBoot整合Kafka

    1.概念:SpringBoot 整合消息服务2.具体内容对于异步消息组件在实际的应用之中会有两类:· JMS:代表作就是 ActiveMQ,但是其性能不高,因为其是用 java 程序实现的:· AMQ ...

  2. springboot整合redis消息队列

    前言 消息队列作为一种常用的异步通信解决方案,而redis是一款高性能的nosql产品,今天就给大家介绍一下,如何使用redis实现消息队列,并整合到springboot. 两个消息模型 1. 队列模 ...

  3. kafka 安装使用 /springboot整合kafka /消息投递机制以及存储策略 /副本处理机制

    一.背景 1.基本信息 Kafka是由Apache软件基金会开发的一个开源流处理平台,由Scala和Java编写.Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者在网站中的所有动作流 ...

  4. SpringBoot整合分布式消息平台Pulsar

    作为优秀的消息流平台,Pulsar 的使用越来越多,这篇文章讲解 Pulsar 的 Java 客户端. 部署 Pulsar Pulsar 的部署方式主要有 3 种,本地安装二进制文件.docker 部 ...

  5. springboot整合kafka_springboot整合kafka实现消息的发送消费

    如下是springboot整合kafka的一个案例,方便需要的小伙伴. 启动kafka Server cd 到kafka的bin目录下:前提是启动zk./kafka-server-start.sh / ...

  6. SpringBoot整合activeMQ消息队列手动签收(Session.CLIENT_ACKNOWLEDGE)为什么失效啊?

    今天在家隔离办公,不太忙,然后就琢磨起来消息队列activeMQ的消息事务来解决分布式事务,但是奈何在SpringBoot整合activeMQ时,其消费者手动签收消息时出现了问题-->当acti ...

  7. Springboot 整合Websocket+Stomp协议+RabbitMQ做消息代理 实例教程

    前言 如果你还没有了解过websocket,关于整合websocket的简单入门使用,可以先看看我这篇: <SpringBoot 整合WebSocket 简单实战案例> https://b ...

  8. 在线聊天室的消息单聊的实现——springboot整合WebSocket(二)

    一.声明 项目的搭建请大家移步到:在线聊天室的消息群聊的实现--springboot整合WebSocket(一) 单聊的实现是在群聊项目上进行延申改造的. 二.引入依赖 <dependency& ...

  9. springboot整合rocketMQ记录 实现发送普通消息,延时消息

    一.为什么选择RocketMQ消息队列?(可跳过看三的整合代码实例) 首先RocketMQ是阿里巴巴自研出来的,也已开源.其性能和稳定性从双11就能看出来,借用阿里的一句官方介绍:历年双 11 购物狂 ...

  10. springboot整合websocket实现消息推送

    springboot整合websocket 1.WebSocket介绍与原理 介绍:WebSocket是HTML5一种新的协议.它实现了浏览器与服务器全双工通信.一开始的握手需要借助HTTP请求完成. ...

最新文章

  1. go使用SQLite数据库
  2. bat 服务启动脚本
  3. 自从用python写了个自动弹幕脚本后,各大主播来找我,净赚十万!赶紧收藏!!
  4. [原创]RedisDesktopManager工具使用介绍
  5. 我们是已经谈不起恋爱的80后
  6. transformer李宏毅讲解视频及decoder讲解
  7. 计算机丢失msvcrtdll怎么修复,雨林木风修复msvcrtdll 【操作方案】 的详细_
  8. 中国英语学习论坛(2:考 研 英 语 资 料 索 引)
  9. C语言 Fibonacci数列(递推)
  10. AD 画PCB 布线时,连线就变绿
  11. oracle minus intersect,minus,oracle中INTERSECTMINUS用法
  12. 密码算法测试向量——目录
  13. java类 家族成员 姓氏_极其罕见的四大姓氏,若你还姓这个,恭喜你,你的家族大有来头!...
  14. vc 鲜为人知的 __if_exists
  15. C++函数UpdateData()有什么作用?
  16. Emgucv使用中常用函数总结
  17. 如何开启 vue 项目
  18. 【非原创】完全用Linux工作(下)(r4笔记第86天)
  19. 设计评选优秀教师和优秀学生候选人的程序。
  20. 兄弟连视频教程下载地址汇总-2014(转)

热门文章

  1. 辽宁大学计算机考研资料汇总
  2. Qt 实现 异形 窗体按钮
  3. 可能导致不可接受的信息安全事件发生的核电站事故。
  4. 移动互联网如何重新定义『明星』?
  5. Unity3D C# Socket通信详解之基础介绍
  6. Kubernetes添加带Quota限额的CephFS StorageClass
  7. 亚马逊 JDK下载地址
  8. C语言--判断一个年份是否是闰年(详解)
  9. html捉虫游戏,《小青蛙捉虫》托班体育游戏教案
  10. 计算机二级考试试题结构,2008年4月计算机等级考试二级C++语言试题结构分析