Bootstrap

微服务分布式电商项目高级篇《谷粒商城》学习笔记

文章目录

一、全文检索-ElasticSearch

1.基础概念

在这里插入图片描述
ES 对应 mysql
索引Index 对应 insert
类型Type 对应 不同表
一条条的记录称为文档Document 对应 一条条的记录称为记录

概念理解:数据库=》数据表=》数据=》属性(列名)

1.1倒排索引

在这里插入图片描述

2.docker安裝elasticsearch、kibana

3.初步检索

3.1 _cat

GET/_cat/nodes:查看所有节点
GET/_cat/health:查看es 健康状况
GET/_cat/master:查看主节点
GET/_cat/indices:查看所有索引,等价于数据库的show databases;
在这里插入图片描述
总结:用于查看elasticsearch的基本信息

3.2 _put

保存一个数据,保存在哪个索引的哪个类型下,指定用哪个唯一标识
PUT customer/external/1;在 customer索引下的 external类型下保存1号数据为
PUT customer/external/1

语法
{
“name”: “John Doe”
}
PUT和 POST都可以,
POST 新增。如果不指定id,会自动生成id。指定id就会修改这个数据,并新增版本号
PUT可以新增可以修改。PUT必须指定id;由于PUT需要指定id,我们一般都用来做修改操作,不指定id会报错。

3.2.1 put操作

携带id新增
在这里插入图片描述
携带id更新
在这里插入图片描述

不携带id报错
在这里插入图片描述
3.2.2 post操作

携带id新增
在这里插入图片描述
携带id更新
在这里插入图片描述

不携带id新增并生成id唯一值
在这里插入图片描述

3.3 查看文档

_get查询数据&乐观锁字段
在这里插入图片描述
3.3.1 查询数据信息
在这里插入图片描述
3.3.2 A B同时操作更新

A更新name为 “name”: “yellow”
在这里插入图片描述

B更新name为 “name”: “red”
在这里插入图片描述
修改seq_no值重新操作更新,更新成功,seq_no会发生变化
在这里插入图片描述
注:primary_term代表机器重启,重启会发生变化

总结:A B修改同一条记录,假设版本号1,A改了-版本号更新2,B再更改则失败(版本号发生变化了)=》此操作过程请求需要携带看到的数据记录版本号

3.4 更新文档

put&post修改数据
在这里插入图片描述
在这里插入图片描述

注意:_update更新,会对比原来数据,若没有新数据,version和seq_no不会发生变化,即什么都不变。修改的数据发生变化才会更新版本号等其他值。

3.5 删除数据&bulk批量操作导入样本测试数据

在这里插入图片描述
在这里插入图片描述

使用kibana客户端操作
在这里插入图片描述
在这里插入图片描述
样本测试数据
在这里插入图片描述
执行
在这里插入图片描述
在这里插入图片描述

3.6 两种查询方式

在这里插入图片描述
在这里插入图片描述
实例
在这里插入图片描述

3.7 QueryDSL基本使用&match_all

在这里插入图片描述

3.8 match 匹配查询

在这里插入图片描述
若是查询字符串,进行分词+全文检索

案列:
在这里插入图片描述
注:_score代表查询命中得分
全文检索按照评分进行排序,会对检索条件进行分词匹配。

3.9 match_phrase 短语匹配

在这里插入图片描述
在这里插入图片描述
注意:不分词检索

4.0 multi_match 多字段匹配

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
注意:分词+全文检索

4.2 bool 复合查询

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.3 filter结果过滤

在这里插入图片描述
filter不会计算相关性得分
在这里插入图片描述
在这里插入图片描述

4.4 term

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.5 aggregations 执行聚合

在这里插入图片描述
1.搜索address中包含mill的所有人的年龄分布以及平均年龄及平均薪资
在这里插入图片描述
在这里插入图片描述
2.按照年龄聚合,并且请求这些年龄段的这些人的平均薪资
在这里插入图片描述
3.查出所有年龄分布,并且这些年龄段中M的平均薪资和F的平均薪资以及这个年龄段的总体平均薪资
在这里插入图片描述

4.6 映射-mapping创建

在这里插入图片描述
在这里插入图片描述

4.7 添加新的字段映射

在这里插入图片描述
在这里插入图片描述

4.8 更新映射&数据迁移

在这里插入图片描述
数据迁移(创建新的索引)
在这里插入图片描述
在这里插入图片描述

4.9 分词&安装ik分词

在这里插入图片描述
分词
在这里插入图片描述
对于中文需要专门安装分词器
在这里插入图片描述

安装ik分词器(安装过程忽略)=>用于支持中文分词
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.0 自定义扩展词库

在这里插入图片描述
在这里插入图片描述
使用nginx配置
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

4.SpringBoot中使用Elasticsearch Java Rest Client

在这里插入图片描述
1、新建项目=》new module
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
配置信息:略

测试保存
在这里插入图片描述
在这里插入图片描述

5.sku在es中存储模型分析

在这里插入图片描述
在这里插入图片描述
1Mb=1024kb
1G=1024Mb
在这里插入图片描述
100万个请求:32kb*1000000=32000mb=32G =>网络阻塞

PUT product
{
  "mappings":{
    "properties": {
      "skuId":{
        "type":"long"
      },
      "spuId":{
        "type":"keyword"
      },
      "skuTitle":{
        "type":"text",
        "analyzer": "ik_smart"
      },
      "skuPrice":{
        "type":"keyword"
      },
      "skuImg":{
        "type":"keyword",
        "index":false,
        "doc_values":false
      },
      "saleCount":{
        "type":"long"
      },
      "hasStock":{
        "type":"boolean"
      },
      "hasScore":{
        "type":"long"
      },
      "brandId":{
        "type":"long"
      },
      "catalogId":{
        "type":"long"
      },
      "brandName":{
        "type":"keyword",
        "index":false,
        "doc_values":false
      },
      "brandImg":{
        "type":"keyword",
        "index":false,
        "doc_values":false        
      },
      "catalogName":{
        "type":"keyword",
        "index":false,
        "doc_values":false          
      },
      "attrs":{
        "type":"nested",
        "properties": {
          "attrId":{
            "type":"long"
          },
          "attrName":{
              "type":"keyword",
              "index":false,
              "doc_values":false   
          },
          "attrValue":{
            "type":"keyword"
          }
        }
      }
    }
  }
}

GET /product/_search

6.nested数据类型场景

nested嵌入式的
在这里插入图片描述
扁平化
在这里插入图片描述
嵌入式
在这里插入图片描述
在这里插入图片描述

二、thymeleaf模板引擎

1.项目微服务

在这里插入图片描述

1.1 添加thymeleaf依赖

<!--模板引擎:thymeleaf-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

1.2 thymeleaf-starter:关闭缓存

spring:
  thymeleaf:
    cache: false

1.3 添加静态资源

在这里插入图片描述

1.4 访问http://localhost:10000/

在这里插入图片描述
注:SpringBoot,访问项目的时候,默认会找index

1.5 MVC默认配置参考

WebMvcAutoConfiguration.class

2.Nginx+Windows搭建域名访问环境

在这里插入图片描述
在这里插入图片描述

2.1 通过mall.com替代localhost:10000访问商品首页

2.1.1 虚拟机地址映射到mall.com
在这里插入图片描述
2.1.2 mall.com:9200 可以访问到es等
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
注:即域名映射ip

2.2 通过mall.com映射localhost:10000到商品首页

在这里插入图片描述
2.2.1 nginx描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2.2.2 nginx配置

mall.com文件名需改为mall.conf
在这里插入图片描述
在这里插入图片描述
配置完重启下nginx: docker restart nginx

2.2.3 文件名写错修改
在这里插入图片描述
2.2.4 访问mall.com
在这里插入图片描述

2.2.5 流程描述

在这里插入图片描述

2.3 通过mall.com映射nginx,nginx路由到网关,再网关请求服务

在这里插入图片描述
在这里插入图片描述
docker restart nginx
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

三、压力测试

1.介绍

## 1.介绍

在这里插入图片描述

2.JMeter

官网下载:https://jmeter.apache.org/download_jmeter.cgi

在这里插入图片描述

2.1 线程组

在这里插入图片描述
在这里插入图片描述
注:循环次数,若为10,则代表每个线程发10次请求,若线程数为200,则总共发2000个请求

2.2 http请求

在这里插入图片描述
在这里插入图片描述

2.3 查看结果树

在这里插入图片描述
在这里插入图片描述
测试效果
在这里插入图片描述

2.4 汇总报告

在这里插入图片描述
在这里插入图片描述
测试效果:注意吞吐量
在这里插入图片描述
吞吐量:每秒钟系统能够处理的请求数、任务数。

2.5 聚合报告

在这里插入图片描述
在这里插入图片描述
测试效果
在这里插入图片描述

2.6 汇总图

在这里插入图片描述
在这里插入图片描述
测试效果:根据勾选如中位数显示图形-显示效果
在这里插入图片描述

2.7 启动测试

在这里插入图片描述
保存测试计划-方便下次
在这里插入图片描述

2.8 响应数据

在这里插入图片描述

2.9 清空报告(每个都选中然后清除)

在这里插入图片描述

2.10 测试新接口

在这里插入图片描述

3.JMeter Address Already in use错误解决

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
设置回收端口时间
在这里插入图片描述
更多参考windows帮助文档
在这里插入图片描述
退出注册表,重启计算机才生效

4.性能监控-堆内存、垃圾回收、jconsole与jvisualvm

在这里插入图片描述
CPU密集型:如查询出数据,然后进行处理,排序,筛选等
IO密集型:如从redis缓存读取数据,读文件等

4.1 JVM内存模型

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
元数据区:用于直接操作物理地址

4.2 垃圾回收

在这里插入图片描述
在这里插入图片描述
注:假设进行100次 MinorGc花费1s。但10次Full Gc就要花费1s,非常慢(慢将近10倍),尽量减少Full Gc的次数。

4.3 java监视和管理控制台

在这里插入图片描述

4.3.1 jconsole

在这里插入图片描述
双击项目查看内存信息
在这里插入图片描述

4.3.2 jvisualvm

在这里插入图片描述
在这里插入图片描述
1)、下载插件
在这里插入图片描述
2)、问题解决方案

1.打开 https://visualvm.github.io/pluginscenters.html
2.查看jdk版本
在这里插入图片描述
3.使用https://visualvm.github.io/archive/uc/8u40/updates.xml.gz在这里插入图片描述
在这里插入图片描述
3)、安装GC插件-查看完整GC过程
在这里插入图片描述
重启jvisualvm
在这里插入图片描述

4.4 中间件对性能的影响

在这里插入图片描述

4.5 优化吞吐量测试

在这里插入图片描述
在这里插入图片描述

4.5.1 日志
在这里插入图片描述

4.5.2 索引
在这里插入图片描述

4.6 nginx动静分离

在这里插入图片描述
在这里插入图片描述

将静态资源上传到linux下的nginx/html/static下
在这里插入图片描述

配置nginx访问静态资源
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
注:root用于配置资源路径

静态资源添加/static访问
在这里插入图片描述

4.7 JVM参数

在这里插入图片描述

4.8 优化三级分类

在这里插入图片描述

四、缓存

在这里插入图片描述
在这里插入图片描述
伪代码
在这里插入图片描述

1.本地缓存与分布式缓存

在这里插入图片描述
在这里插入图片描述
分布式下解决方案
在这里插入图片描述

2.整合redis

2.1 导入依赖

<!--整合redis-->
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
</dependency>

项目其他模块使用了2.2.4.RELEASE,这里使用下面配置

<!--整合redis-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <version>2.2.4.RELEASE</version>
</dependency>

2.2 核心代码

RedisAutoConfiguration.class=>StringRedisTemplate

2.3 配置redis信息

  redis:
    host: xxx.xxx.xxx.xxx
    port: 6379
    passsword:

2.4 使用StringRedisTemplate操作redis

在这里插入图片描述

2.5 使用redis优化三级分类数据

在这里插入图片描述
在这里插入图片描述

2.6 使用jedis

<!--整合redis-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <version>2.2.4.RELEASE</version>
    <exclusions>
        <exclusion>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.1.0</version>
</dependency>

注:
=>使用lettuce、jedis操作redis的底层客户端。Spring再次封装redisTemplate
=>即无论使用ettuce还是jedis,都可以使用redisTemplate操作redis
在这里插入图片描述

3.缓存穿透、雪崩、击穿

3.1 缓存穿透

在这里插入图片描述

3.2 缓存雪崩

在这里插入图片描述

3.3 缓存击穿

在这里插入图片描述

3.4 总结

/**
 *  1、空结果缓存:解决缓存穿透
 *  2、设置过期时间(加随机值):解决缓存雪崩
 *  3、加锁:解决缓存击穿
 */

3.5 本地锁解决缓存击穿

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.6 分布式锁

在这里插入图片描述

3.6.1 本地锁问题

启动多个服务:可以复制10001,10002,10003启动多个服务
在这里插入图片描述
在这里插入图片描述
进行压测
在这里插入图片描述
在这里插入图片描述

3.6.2 使用分布式锁解决本地锁问题

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.Redisson

4.1 概述

在这里插入图片描述

4.2 添加依赖

<!--以后使用redisson作为所有分布式锁,分布式对象等功能框架-->
<dependency>
   <groupId>org.redisson</groupId>
   <artifactId>redisson-spring-boot-starter</artifactId>
   <version>3.13.5</version>
</dependency>

4.3 配置redisson

官方文档:
可参考:https://blog.csdn.net/liu320yj/article/details/109026854

@Configuration
public class MyRedissonConfig {

    /**
     * 所有对Redisson的使用都是通过RedissonClient对象
     * @return
     * @throws IOException
     */
    @Bean(destroyMethod = "shutdown")
    public RedissonClient redisson() throws IOException {
        //1、创建配置
        Config config = new Config();
        config.useSingleServer().setAddress("redis://xxx.xxx.xxx.xxx:6379");
        //2、根据Config创建出RedissonClient示例
        RedissonClient redissonClient = Redisson.create(config);
        return redissonClient;
    }

}

4.4 使用redisson可重入锁

在这里插入图片描述

4.5 使用redisson读写锁

在这里插入图片描述
在这里插入图片描述

4.6 使用redisson信号量

在这里插入图片描述
在这里插入图片描述

4.7 使用redisson闭锁

在这里插入图片描述
在这里插入图片描述

4.8 缓存数据一致性

4.8.1 双写模式

在这里插入图片描述

4.8.2 失效模式

在这里插入图片描述

4.8.3 解决方案

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

5.Spring Cache

https://docs.spring.io/spring-framework/docs/5.2.19.RELEASE/spring-framework-reference/integration.html#cache-jsr-107
https://docs.spring.io/spring-framework/docs/5.2.19.RELEASE/spring-framework-reference/integration.html#cache-spel-context

5.1 简介

在这里插入图片描述
在这里插入图片描述
org.springframework.cache.CacheManager
org.springframework.cache.Cache

5.2 整合SpringCache简化缓存开发

5.2.1 引入依赖

spring-boot-starter-cache、spring-boot-starter-data-redis

<!--整合redis-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <version>2.2.4.RELEASE</version>
    <exclusions>
        <exclusion>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.1.0</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration
注意
CacheConfigurations.getConfigurationClass(types[i])
Class<?> configurationClass = MAPPINGS.get(cacheType);

static {
		Map<CacheType, Class<?>> mappings = new EnumMap<>(CacheType.class);
		mappings.put(CacheType.GENERIC, GenericCacheConfiguration.class);
		mappings.put(CacheType.EHCACHE, EhCacheCacheConfiguration.class);
		mappings.put(CacheType.HAZELCAST, HazelcastCacheConfiguration.class);
		mappings.put(CacheType.INFINISPAN, InfinispanCacheConfiguration.class);
		mappings.put(CacheType.JCACHE, JCacheCacheConfiguration.class);
		mappings.put(CacheType.COUCHBASE, CouchbaseCacheConfiguration.class);
		mappings.put(CacheType.REDIS, RedisCacheConfiguration.class);
		mappings.put(CacheType.CAFFEINE, CaffeineCacheConfiguration.class);
		mappings.put(CacheType.SIMPLE, SimpleCacheConfiguration.class);
		mappings.put(CacheType.NONE, NoOpCacheConfiguration.class);
		MAPPINGS = Collections.unmodifiableMap(mappings);
	}
5.2.2 写配置

1)、自动配置了哪些
CacheAutoConfiguration会导入RedisCacheConfiguration;
自动配好了缓存管理器RedisCacheManager

2)、配置使用redis作为缓存
在这里插入图片描述

3)、测试使用缓存
在这里插入图片描述

@Cacheable: Triggers cache popuLation.触发将数据保存到缓存的操作
@cacheEvict:Triggers cache eviction.触发将数据从缓存删除的操作
@CachePut: Updatcs the cache without intcrfcring with the mcthod execution.不影响方法执行更新缓存
@Caching: Regroups multiple cache operations to be applied on a method.组合以上多个操作
@CacheConfig: Shares some common cache-rclated settings at class-level.在类级别共享缓存的相同配置

3.1)、开启缓存功能:@EnableCaching
在这里插入图片描述
3.2)、只需要注解就能完成缓存操作
在这里插入图片描述
调用方法
在这里插入图片描述

5.2.3 自定义配置

在这里插入图片描述
指定缓存的数据存活时间
在这里插入图片描述
在这里插入图片描述
指定缓存使用的key
在这里插入图片描述
在这里插入图片描述
数据保存为json格式

#application.properties
spring.cache.type=redis
spring.cache.redis.time-to-live=3600000

spring.cache.redis.use-key-prefix=true
#如果指定了前缀就用我们指定的前缀,如果没有就默认使用缓存的名字作为前缀
#spring.cache.redis.key-prefix=CACHE
#是否缓存控制:解决缓存穿透
spring.cache.redis.cache-null-values=true
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.cache.CacheProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@EnableConfigurationProperties(CacheProperties.class)
@Configuration
@EnableCaching
public class MyCacheConfig {

    /*@Autowired
    CacheProperties cacheProperties;*/

    /**
     * 配置文件中的东西没有用上:
     * 1、原来和配置文件绑定的配置类是这样子的
     *      @ConfigurationProperties(prefix = "spring.cache")
     *      public class CacheProperties
     * 2、要让他生效
     *      @EnableConfigurationProperties(CacheProperties.class)
     * @return
     */
    @Bean
    RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties){

        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
        //config = config.entryTtl();
        config = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));

        config = config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));

        //将配置文件中的所有配置都生效
        CacheProperties.Redis redisProperties = cacheProperties.getRedis();
        if (redisProperties.getTimeToLive() != null) {
            config = config.entryTtl(redisProperties.getTimeToLive());
        }

        if (redisProperties.getKeyPrefix() != null) {
            config = config.prefixCacheNameWith(redisProperties.getKeyPrefix());
        }

        if (!redisProperties.isCacheNullValues()) {
            config = config.disableCachingNullValues();
        }

        if (!redisProperties.isUseKeyPrefix()) {
            config = config.disableKeyPrefix();
        }
        return config;

    }
}

5.2.4 使用注解

@CacheEvict : 触发将数据从缓存删除的操作
在这里插入图片描述
@Caching: 组合多种缓存操作
在这里插入图片描述
@CachePut:双写模式,用于更新缓存

5.2.5 Spring-Cache原理与不足

在这里插入图片描述

6.搭建搜索页面

6.1 导入资源到nginx,配置搜索静态资源到search

在这里插入图片描述

6.2 在首页点击搜索需要跳转到搜索页面

在这里插入图片描述
在这里插入图片描述
配置nginx:把search.mall.com也转发到网关
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
网关根据$host负载均衡到gulimall-search
在这里插入图片描述
跳转到搜索页面
在这里插入图片描述

6.3 检索业务分析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6.4 使用ES测试复杂查询

search.mall.com/list.html?catalog3ld=225&keyword=华为&brandld=1&brandld=2&attrs=1_5.56以上&attrs=2_白色:蓝色
在这里插入图片描述

GET product/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "skuTitle": "华为"
          }
        }
      ],
      "filter": [
        {
          "term": {
            "catalogId": "225"
          }
        },
        {
          "terms": {
            "brandId": [
              "1",
              "2",
              "9"
            ]
          }
        },
        {
          "nested": {
            "path": "attrs",
            "query": {
              "bool": {
                "must": [
                  {
                    "term": {
                      "attrs.attrId": {
                        "value": "1"
                      }
                    }
                  },
                  {
                    "terms": {
                      "attrs.attrValue": [
                        "aaa",
                        "bbb"
                      ]
                    }
                  }
                ]
              }
            }
          }
        },
        {
          "range": {
            "skuPrice": {
              "gte": 0,
              "lte": 9000
            }
          }
        }
      ]
    }
  },
  "sort": [
    {
      "skuPrice": {
        "order": "desc"
      }
    }
  ],
  "from":0,
  "size":2,
  "highlight":{
    "fields": {"skuTitle":{}}, 
    "pre_tags": "<b style='color:red'>",
    "post_tags": "</b>"
  }
}

模糊匹配,过滤(按照属性,分类,品牌,价格区间,库存),排序,分页,高亮,聚合分析

6.5 聚合分析

1.修改映射

先查看原映射:GET product/_mapping

{
  "product" : {
    "mappings" : {
      "properties" : {
        "attrs" : {
          "type" : "nested",
          "properties" : {
            "attrId" : {
              "type" : "long"
            },
            "attrName" : {
              "type" : "keyword",
              "index" : false,
              "doc_values" : false
            },
            "attrValue" : {
              "type" : "keyword"
            }
          }
        },
        "brandId" : {
          "type" : "long"
        },
        "brandImg" : {
          "type" : "keyword",
          "index" : false,
          "doc_values" : false
        },
        "brandName" : {
          "type" : "keyword",
          "index" : false,
          "doc_values" : false
        },
        "catalogId" : {
          "type" : "long"
        },
        "catalogName" : {
          "type" : "keyword",
          "index" : false,
          "doc_values" : false
        },
        "hasScore" : {
          "type" : "long"
        },
        "hasStock" : {
          "type" : "boolean"
        },
        "hotScore" : {
          "type" : "long"
        },
        "saleCount" : {
          "type" : "long"
        },
        "skuId" : {
          "type" : "long"
        },
        "skuImg" : {
          "type" : "keyword",
          "index" : false,
          "doc_values" : false
        },
        "skuPrice" : {
          "type" : "keyword"
        },
        "skuTitle" : {
          "type" : "text",
          "analyzer" : "ik_smart"
        },
        "spuId" : {
          "type" : "keyword"
        }
      }
    }
  }
}

修改映射

PUT mall_product
{
  "mappings" : {
    "properties" : {
      "attrs" : {
        "type" : "nested",
        "properties" : {
          "attrId" : {
            "type" : "long"
          },
          "attrName" : {
            "type" : "keyword"
          },
          "attrValue" : {
            "type" : "keyword"
          }
        }
      },
      "brandId" : {
        "type" : "long"
      },
      "brandImg" : {
        "type" : "keyword"
      },
      "brandName" : {
        "type" : "keyword"
      },
      "catalogId" : {
        "type" : "long"
      },
      "catalogName" : {
        "type" : "keyword"
      },
      "hasScore" : {
        "type" : "long"
      },
      "hasStock" : {
        "type" : "boolean"
      },
      "hotScore" : {
        "type" : "long"
      },
      "saleCount" : {
        "type" : "long"
      },
      "skuId" : {
        "type" : "long"
      },
      "skuImg" : {
        "type" : "keyword"
      },
      "skuPrice" : {
        "type" : "keyword"
      },
      "skuTitle" : {
        "type" : "text",
        "analyzer" : "ik_smart"
      },
      "spuId" : {
        "type" : "keyword"
      }
    }
  }
}  

查看映射信息:GET mall_product/_mapping

查看数据:GET mall_product/_search

进行数据迁移

#迁移数据
POST _reindex
{
  "source":{
    "index":"product"
  },
  "dest": {
    "index":"mall_product"
  }
}

#如果是嵌入式的属性,查询,聚合,分析都应该用嵌入式的

#检索
GET mall_product/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "skuTitle": "华为"
          }
        }
      ],
      "filter": [
        {
          "term": {
            "catalogId": "225"
          }
        },
        {
          "terms": {
            "brandId": [
              "1",
              "2",
              "9"
            ]
          }
        },
        {
          "nested": {
            "path": "attrs",
            "query": {
              "bool": {
                "must": [
                  {
                    "term": {
                      "attrs.attrId": {
                        "value": "1"
                      }
                    }
                  },
                  {
                    "terms": {
                      "attrs.attrValue": [
                        "aaa",
                        "bbb"
                      ]
                    }
                  }
                ]
              }
            }
          }
        },
        {
          "range": {
            "skuPrice": {
              "gte": 0,
              "lte": 9000
            }
          }
        }
      ]
    }
  },
  "sort": [
    {
      "skuPrice": {
        "order": "desc"
      }
    }
  ],
  "from":0,
  "size":2,
  "highlight":{
    "fields": {"skuTitle":{}}, 
    "pre_tags": "<b style='color:red'>",
    "post_tags": "</b>"
  },
    "aggs":{
    "brand_agg":{
      "terms": {
        "field":"brandId",
        "size":10
      },
      "aggs": {
        "brand_name_agg": {
          "terms": {
            "field": "brandName",
            "size": 10
          }
        },
        "brand_img_agg":{
          "terms": {
            "field": "brandImg",
            "size": 10
          }
        }
      }
    },
    "catalog_agg":{
      "terms": {
        "field": "catalogId",
        "size": 10
      },
      "aggs": {
        "catalog_name_agg": {
          "terms": {
            "field": "catalogName",
            "size": 10
          }
        }
      }
    },
    "attr_agg":{
      "nested": {
        "path": "attrs"
      },
      "aggs":{
        "attr_id_agg":{
          "terms": {
            "field":"attrs.attrId",
            "size":10
          },
          "aggs":{
            "attr_name_agg":{
              "terms": {
                "field": "attrs.attrName",
                "size": 10
              }
            },
            "attr_value_agg":{
              "terms": {
                "field": "attrs.attrValue",
                "size": 10
              }
            }
          }
        }
      }
    }
  }
}

五、线程池

1.初始化线程数的4种方式

在这里插入图片描述

1.1 创建方式一

在这里插入图片描述
在这里插入图片描述

1.2 创建方式二

在这里插入图片描述
在这里插入图片描述
通过execute方法

2 好处

在这里插入图片描述

六、 CompletableFuture异步编排

1. 创建异步对象

在这里插入图片描述
可以传入自定义线程池

案例一:
在这里插入图片描述
案例二:可以带返回值
在这里插入图片描述
在这里插入图片描述

2. 计算完成时回调方法

在这里插入图片描述
whenComplete 不用开启新线程
在这里插入图片描述
whenCompleteAsyn 需要开启新线程
在这里插入图片描述
exceptionally 可以用来进行异常处理
在这里插入图片描述
在这里插入图片描述

3. handle

在这里插入图片描述

4. 线程串行化

在这里插入图片描述
thenRunAsync
在这里插入图片描述
thenAcceptAsync
在这里插入图片描述
thenApplyAsync
在这里插入图片描述

5. 两任务组合 - 都要完成

在这里插入图片描述
runAfterBothAsync:不能感知到前两个的结果
在这里插入图片描述
thenAcceptBothAsync:能感知到前两个的结果
在这里插入图片描述
thenCombineAsync:能处理到前两个的结果,有返回值
在这里插入图片描述

6. 两任务组合 - 一个完成

在这里插入图片描述
runAfterEitherAsync:不感知结果,自己没有返回值
在这里插入图片描述
acceptEitherAsync:感知结果,自己没有返回值
在这里插入图片描述
applyToEitherAsync:处理结果,有返回值
在这里插入图片描述
在这里插入图片描述

7. 多任务组合

在这里插入图片描述
allof:所有任务必须完成
在这里插入图片描述
anyOf:只要有一个任务完成
在这里插入图片描述

8. 业务场景

在这里插入图片描述

七. 商品详情

1. 环境搭建

在这里插入图片描述
在这里插入图片描述
静态资源放在nginx上
在这里插入图片描述

2.使用异步编排

2.1 MyThreadConfig

在这里插入图片描述

2.2 ThreadPoolConfigProperties

在这里插入图片描述
在这里插入图片描述

2.3 使用

在这里插入图片描述
在这里插入图片描述

八.认证服务

1. 环境搭建

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
还有thymeleaf也得加上,这里忘记加了
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2.配置域名映射

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

九.短信服务

在这里插入图片描述
在这里插入图片描述
参考:https://blog.csdn.net/qq_44035485/article/details/121174570

 <!--短信-->
 <dependency>
     <groupId>com.aliyun</groupId>
     <artifactId>tea-openapi</artifactId>
     <version>0.0.19</version>
 </dependency>
 <dependency>
     <groupId>com.aliyun</groupId>
     <artifactId>dysmsapi20170525</artifactId>
     <version>2.0.6</version>
 </dependency>

 <!--整合redis-->
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-data-redis</artifactId>
     <version>2.2.4.RELEASE</version>
     <exclusions>
         <exclusion>
             <groupId>io.lettuce</groupId>
             <artifactId>lettuce-core</artifactId>
         </exclusion>
     </exclusions>
 </dependency>
 <dependency>
     <groupId>redis.clients</groupId>
     <artifactId>jedis</artifactId>
     <version>3.1.0</version>
 </dependency>

十.密码加密

在这里插入图片描述

1.MD5

String s = DigestUtils.md5Hex(“123456”);

不可逆(使用彩虹表可以破解),MD5不能直接进行密码的加密存储

2.盐值(知道盐也能破解)

String s = Md5Crypt.md5Crypt(“123456”.getBytes(), “abc”);

3.BCrypt

盐值使用特别方式

BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String encode = passwordEncoder.encode("123456");

十一.OAuth2.0

1.简介

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.流程(微博)

在这里插入图片描述
在这里插入图片描述
注:
1.使用code(有效期内可换取)换取AccessToken,Code只能使用一次
2.同一个用户的accessToken一段时间是不会变化的,即使多次获取。
在这里插入图片描述

3.ums_member表添加字段

在这里插入图片描述
在这里插入图片描述

4.session

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.单点登录

spring session共享不能解决以下问题
在这里插入图片描述
在这里插入图片描述
配置hosts文件
在这里插入图片描述

认证服务
在这里插入图片描述
在这里插入图片描述
客户端服务
在这里插入图片描述
在这里插入图片描述
流程
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
问题client1.com可以登录了但
client2.com:8081//employees还是不能登录

复制一份client服务作为client2,修改端口为8082
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

十二.购物车

1.环境搭建

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.静态资源动静分离

在这里插入图片描述

3.购物车需求

在这里插入图片描述

4.从需求分析出模型

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.ThreadLocal

在这里插入图片描述

十三.RabbitMQ

1.Message Queue消息队列简介

使用场景
在这里插入图片描述
在这里插入图片描述

2.消息中间件常用概念

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.RabbitMQ简介

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.RabbitMQ运行机制

在这里插入图片描述

4.1 Exchange类型

direct、fanout、topic
在这里插入图片描述
fanout:广播类型
在这里插入图片描述
topic:主题类型(重点)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.Springboot整合RabbitMQ

5.1 引入spring-boot-starter-amqp

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

5.2 application.yml配置

spring.rabbitmq.host=192.168.136.129
spring.rabbitmq.port=5672
spring.rabbitmq.virtual-host=/

5.3 测试RabbitMQ

5.3.1 AmqpAdmin-管理组件
    @Autowired
    AmqpAdmin amqpAdmin;

    /**
     * 1、如何创建Exchange[hello.java.exchange]、Queue、Binding
     *      1)、使用AmqpAdmin进行创建
     */
    @Test
    void createExchange() {
        //DirectExchange(String name, boolean durable, boolean autoDelete, Map<String, Object> arguments)
        //durable:是否持久化
        DirectExchange directExchange = new DirectExchange("hello-java-exchange",true,false);
        amqpAdmin.declareExchange(directExchange);
        log.info("exchange:[{}]创建成功","hello-java-exchange");
    }

    @Test
    void createQueue() {
        //exclusive:是否排他的,false:允许同时有多个连接到此queue
        Queue queue = new Queue("hello-java-queue",true,false,false);
        amqpAdmin.declareQueue(queue);
        log.info("queue:[{}]创建成功","hello-java-queue");
    }

    @Test
    void createBinding(){
        // String destination【目的地】,
        // DestinationType destinationType 【目的地类型】
        // String exchange【交换机】,
        // String routingKey【路由键】,
        // Map<String, Object> arguments【自定义参数】
        // 将exchange指定的交换机和destination目的地进行绑定,使用routingKey作为指定的路由键
        Binding binding = new Binding("hello-java-queue", Binding.DestinationType.QUEUE,
                "hello-java-exchange",
                "hello.java",null);
        amqpAdmin.declareBinding(binding);
        log.info("binding:[{}]创建成功","hello-java-binding");
    }
5.3.2 RabbitTemplate-消息发送处理组件
    @Test
    void sendMessageTests() {

        //1、发送消息,如果发送的消息是个对象,我们会使用序列化机制,将对象写出去。对象必须实现Serializable
        String msg = "Hello World";
        OrderReturnReasonEntity entity = new OrderReturnReasonEntity();
        entity.setId(1L);
        entity.setCreateTime(new Date());

        //2、发送的对象类型的消息,可以是一个json
        for (int i = 0;i<10;i++) {
            if(i%2==0) {
                entity.setName("Vc" + i);
                rabbitTemplate.convertAndSend("hello-java-exchange", "hello.java", entity);
            }else {
                OrderEntity orderEntity = new OrderEntity();
                orderEntity.setOrderSn(UUID.randomUUID().toString());
                rabbitTemplate.convertAndSend("hello-java-exchange","hello.java",orderEntity);
            }
            log.info("消息发送完成{}" + entity);
        }
    }

5.3.3 RabbitListener&RabbitHandle接收消息
@RabbitListener(queues = {"hello-java-queue"})
@Service("orderItemService")
public class OrderItemServiceImpl extends ServiceImpl<OrderItemDao, OrderItemEntity> implements OrderItemService 
    /**
     * queue:声明需要监听的所有队列
     *
     * org.springframework.amqp.core.Message
     *
     * 参考可以写一下类型
     * 1、Message message:原生消息详细信息。头+体
     * 2、T<发送的消息的类型> OrderReturnReasonEntity content
     * 3、Channel channel: 当前传输数据的通道
     *
     * Queue: 可以很多人都来监听。只要收到消息,队列删除消息,而且只能有一个收到此消息
     * 场景:
     *      1)、订单服务启动多个;同一个消息,只能有一个客户端收到
     *      2)、只有一个消息完全处理完,方法运行结束,我们就可以接收到下一个消息
     * @param message
     */
    //RabbitListener(queues = {"hello-java-queue"})
    @RabbitHandler
    public void recieveMessage(Message message,
                               OrderReturnReasonEntity content,
                               Channel channel) throws InterruptedException {
        //{"id":1,"name":"哈哈","sort":null,"status":null,"createTime":1652100907404}
        System.out.println("接收到消息..."+content);
        byte[] body = message.getBody();
        //消息头属性信息
        MessageProperties properties = message.getMessageProperties();
        Thread.sleep(3000);
        System.out.println("消息处理完成=》"+content.getName());
    }

    @RabbitHandler
    public void recieveMessage2(OrderEntity content) {
        //{"id":1,"name":"哈哈","sort":null,"status":null,"createTime":1652100907404}
        System.out.println("接收到消息..."+content);
    }

}

5.4 RibbitMQ消息确认机制-可靠抵达(发送端确认)

在这里插入图片描述
在这里插入图片描述
注:springboot.rabbitmq.publisher-confirm 已被弃用.

#新版使用
#开启发送端确认
spring.rabbitmq.publisher-confirm-type=correlated

参考https://blog.csdn.net/z69183787/article/details/109371628
在这里插入图片描述

#开启发送端消息抵达队列的确认
spring.rabbitmq.publisher-returns=true
#只要抵达队列,以异步发送优先回调我们这个return
spring.rabbitmq.template.mandatory=true

5.5 RibbitMQ消息确认机制-可靠抵达(消费端确认)

在这里插入图片描述

#手动ack消息
spring.rabbitmq.listener.simple.acknowledge-mode=manual
    @RabbitHandler
    public void recieveMessage(Message message,
                               OrderReturnReasonEntity content,
                               Channel channel) throws InterruptedException {
        //{"id":1,"name":"哈哈","sort":null,"status":null,"createTime":1652100907404}
        System.out.println("接收到消息..."+content);
        byte[] body = message.getBody();
        //消息头属性信息
        MessageProperties properties = message.getMessageProperties();
        Thread.sleep(3000);
        System.out.println("消息处理完成=》"+content.getName());
        //Channel内按顺序自增
        long deliveryTag = message.getMessageProperties().getDeliveryTag();

        //签收货物,非批量模式
        try {

            if(deliveryTag%2==0){
                //收货
                channel.basicAck(deliveryTag,false);
                System.out.println("签收了货物..."+deliveryTag);
            }else {
                //退货 requeue=false 丢弃 requeue=true 发回服务器,服务器重新入队
                //deliveryTag, multiple, requeue(false不再入队)
                channel.basicNack(deliveryTag,false,false);
                System.out.println("没有签收了货物..."+deliveryTag);
            }
        } catch (Exception e) {
            //网络中断

        }
    }

十四.订单服务

1.搭建订单页面

等待付款
在这里插入图片描述
在这里插入图片描述
订单页
在这里插入图片描述
在这里插入图片描述
结算页
在这里插入图片描述
在这里插入图片描述
收银页
在这里插入图片描述
在这里插入图片描述

2.配置域名服务

在这里插入图片描述

3.订单

3.1 基本概念

在这里插入图片描述

3.2 订单构成

在这里插入图片描述

3.3 订单状态

在这里插入图片描述
在这里插入图片描述

3.4 订单流程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.5 订单确认页模型抽取

在这里插入图片描述
vo略

3.6 Feign远程调用丢失请求头

在这里插入图片描述
解决方案
在这里插入图片描述

@Configuration
public class GulimallFeignConfig {

    @Bean("requestInterceptor")
    public RequestInterceptor requestInterceptor(){
        return new RequestInterceptor() {

            @Override
            public void apply(RequestTemplate template) {
                //1、RequestContextHolder拿到刚进来的这个请求
                ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                HttpServletRequest request = attributes.getRequest(); //旧请求
                //同步请求头数据,Cookie、
                String cookie = request.getHeader("Cookie");
                //给新请求同步了旧请求的cookie
                template.header("Cookie",cookie);

            }
        };
    }

}

3.7 Feign异步调用丢失请求头问题

在这里插入图片描述

    @Override
    public OrderConfirmVo confirmOrder() throws ExecutionException, InterruptedException {
        OrderConfirmVo confirmVo = new OrderConfirmVo();
        MemberRespVo memberRespVo = LoginUserInterceptor.loginUser.get();
        System.out.println("主线程..."+Thread.currentThread().getId());

        //获取之前的请求
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();

        CompletableFuture<Void> getAddressFuture = CompletableFuture.runAsync(() -> {
            //1、远程查询所有的收货地址列表
            System.out.println("member线程..."+Thread.currentThread().getId());
            //每一个线程都来共享之前的请求数据
            RequestContextHolder.setRequestAttributes(requestAttributes);
            List<MemberAddressVo> address = memberFeignService.getAddress(memberRespVo.getId());
            confirmVo.setAddress(address);
        }, executor);

        CompletableFuture<Void> cartFuture = CompletableFuture.runAsync(() -> {
            //2、远程查询购物车所有选中的购物项
            System.out.println("cart线程..."+Thread.currentThread().getId());
            //每一个线程都来共享之前的请求数据
            RequestContextHolder.setRequestAttributes(requestAttributes);
            List<OrderItemVo> items = cartFeignService.getCurrentUserCartItems();
            confirmVo.setItems(items);
            //feign在远程调用之前要构造请求,调用很多的拦截器
            //RequestInterceptor interceptor : requestInterceptors
        }, executor);


        //3、查询用户积分
        Integer integration = memberRespVo.getIntegration();
        confirmVo.setIntegration(integration);

        //4、其他数据自动计算

        //TODO 5、防重令牌

        CompletableFuture.allOf(getAddressFuture,cartFuture).get();

        return confirmVo;
    }

3.8 接口幂等性

一、什么是接口幂等性
在这里插入图片描述
二、哪些情况需要防止
在这里插入图片描述
三、什么情况需要幂等
在这里插入图片描述
四、幂等解决方案

1.token机制
在这里插入图片描述
2.各种锁机制
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3.各种唯一约束
在这里插入图片描述
在这里插入图片描述
4.防重表
在这里插入图片描述
5.全局请求唯一id
在这里插入图片描述

4.订单业务流程

4.1 去结算

在这里插入图片描述

4.2 下订单

在这里插入图片描述

4.3 锁库存

在这里插入图片描述
在这里插入图片描述

5.本地事务

5.1 本地事务在分布式下的问题

在这里插入图片描述

5.2 本地事务

1.事务的基本性质
在这里插入图片描述
在这里插入图片描述
2.事务的隔离级别
在这里插入图片描述
在这里插入图片描述
3.事务的传播行为
在这里插入图片描述
伪代码在这里插入图片描述
同理,c发送生异常,c回滚。b,c不回滚。
注:应该在不同service,直接调用同个类里的事务方法会导致事务失效
在这里插入图片描述
可提供的解决方案:
在这里插入图片描述

  <!-- 引入aop -->
  <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-aop</artifactId>
  </dependency>

主类开启
@EnableAspectJAutoProxy(exposeProxy = true) //开启了aspect动态代理模式,对外暴露代理对象
在这里插入图片描述

6.分布式事务

6.1 为什么有分布式事务

在这里插入图片描述

6.2 CAP定理和BASE理论

一、CAP定理
在这里插入图片描述
在这里插入图片描述
raft动画演示:raft.github.io

二 、面临的问题
在这里插入图片描述

三、BASE理论
在这里插入图片描述
在这里插入图片描述
四、强一致性、弱一致性、最终一致性
在这里插入图片描述

6.3 分布式事务几种方案

6.3.1 2PC模式

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6.3.2 柔性事务-TCC事务补偿型方案

在这里插入图片描述
在这里插入图片描述

6.3.3 柔性事务-最大努力通知型方案

在这里插入图片描述

6.3.4 柔性事务-可靠消息+最终一致性方案(异步确保型)

采用该方案
在这里插入图片描述
注:根据业务场景选择合适方案

7.Seata(可忽略)

在这里插入图片描述

文档:https://seata.io/zh-cn/docs/overview/what-is-seata.html

7.1 Seata是什么

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7.2 创建 UNDO_LOG 表

wms、ums、sms、pms、oms、admin数据库

-- 注意此处0.3.0+ 增加唯一索引 ux_undo_log
CREATE TABLE `undo_log` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `branch_id` bigint(20) NOT NULL,
  `xid` varchar(100) NOT NULL,
  `context` varchar(128) NOT NULL,
  `rollback_info` longblob NOT NULL,
  `log_status` int(11) NOT NULL,
  `log_created` datetime NOT NULL,
  `log_modified` datetime NOT NULL,
  `ext` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

7.3 启动服务

从 https://github.com/seata/seata/releases,下载服务器软件包,将其解压缩。

Usage: sh seata-server.sh(for linux and mac) or cmd seata-server.bat(for windows) [options]
  Options:
    --host, -h
      The address is expose to registration center and other service can access seata-server via this ip
      Default: 0.0.0.0
    --port, -p
      The port to listen.
      Default: 8091
    --storeMode, -m
      log store mode : file、db
      Default: file
    --help

e.g.

sh seata-server.sh -p 8091 -h 127.0.0.1 -m file

在这里插入图片描述

十五.RabbitMQ延时队列(实现定时任务)

1.场景

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.解决方案

在这里插入图片描述
在这里插入图片描述
推荐使用延时队列实现-1
在这里插入图片描述
在这里插入图片描述

3.具体实现

在这里插入图片描述
使用下面方案:
在这里插入图片描述
WareOrderTaskDetailEntity添加wareId,lockStatus字段
在这里插入图片描述
在这里插入图片描述

4.问题

update.s
关单时再去发一个消息

5.消息丢失、积压、重复等解决方案

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

保证消息一定会发送出去,每一个消息都可以做好日志记录。
在这里插入图片描述

CREATE TABLE `mq_message` (
`message_id` char(32) NOT NULL,
`content` text,
`to_exchane` varchar(255) DEFAULT NULL,
`routing_key` varchar(255) DEFAULT NULL,
`class_type` varchar(255) DEFAULT NULL,
`message_status` int(1) DEFAULT '0' COMMENT '0-新建 1-已发送 2-错误抵达 3-已抵达',
`create_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`message_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

十六.支付宝支付

1.流程

1.进入“蚂蚁金服开放平台”

https://open.alipay.com/platform/home.htm

2.创建应用,进行配置测试

2.测试环境

测试环境使用沙箱环境:https://opendocs.alipay.com/open/02np8i

具体流程根据官方文档

十七.秒杀服务

1.秒杀业务

在这里插入图片描述

2.搭建环境

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.定时任务

3.1 cron表达式

可以使用在线cron表达式生成器
在这里插入图片描述
通过空格区分
在这里插入图片描述
注:Spring不支持年

3.1 cron表达式示例

在这里插入图片描述

4.秒杀流程

4.1 基本流程

在这里插入图片描述
在这里插入图片描述
秒杀商品采用该方案
在这里插入图片描述
在这里插入图片描述

4.2 分布下秒杀商品缓存redis问题

在这里插入图片描述

4.3 秒杀设计

在这里插入图片描述
在这里插入图片描述

十八.SpringCloud Alibaba-Sentinel

1.简介

在这里插入图片描述
在这里插入图片描述

2.Sentinel简介

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.使用

看官网文档

github: https://github.com/alibaba/Sentinel

https://github.com/alibaba/spring-cloud-alibaba/wiki/Sentinel

从 release 页面 下载最新版本的控制台 jar 包: https://github.com/alibaba/Sentinel/releases

十九.Sleuth+Zipkin服务链路追踪

1.为什么用

在这里插入图片描述

2.基本术语

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.整合sleuth

在这里插入图片描述

4.整合zipkin可视化观察

在这里插入图片描述
在这里插入图片描述

5.zipkin数据持久化

在这里插入图片描述

;