文章目录

  • MQ
    • 1.为什么要使用MQ? MQ的优点?
    • 2.MQ的优点
    • 3.**如何消息的顺序问题**
    • 3.MQ怎么解决消息的重复消费问题
    • 4.RabbitMQ中有哪些组件?
    • 5.RabbitMQ的工作模式
  • 6.如何保证RabbitMQ消息的可靠传输?
    • cookie
    • Session
    • Token
      • 将对象转换为json
    • JWT令牌
  • Nginx
    • 反向代理
    • 限流
  • 网关
    • 作用
    • 网关负载均衡
    • 网关限流
    • Sentienl
  • Feign
  • 项目介绍
  • 登录
    • JWT令牌
    • 单点登录-Spring security Oauth2
    • 公钥私钥
  • 商品表结构介绍
  • 购物车
    • 登录认证
      • 微服务间调用的令牌认证(令牌的传递)
    • 项目最大困难
  • 订单系统
    • 添加订单
    • 解决超卖问题
    • 秒杀系统

MQ

1.为什么要使用MQ? MQ的优点?

  • 为了解藕,系统跟系统传递消息间是耦合,使用 MQ,A 系统产生一条数据,发送到 MQ 里面去,哪个系统需要数据自己去 MQ 里面消费。
  • 为了异步,减少请求与响应的耗时,给用户更好的体验感
  • 削峰:减少高峰时期对服务器压力。
  • 日志处理 - 解决大量日志传输。
  • 消息通讯 - 消息队列一般都内置了高效的通信机制

2.MQ的优点

1.解藕 2.异步 3.削峰

缺点:考虑一致性问题、如何保证消息不被重复消费、如何保证消息可靠性传输等

3.如何消息的顺序问题

保证生产者 - MQServer - 消费者是一对一对一的关系,假如有两个消费者1,2,消费1消费完后通知MQServer,再发送给消费2,

缺陷:

并行度成问题,会有更多的异常处理

3.MQ怎么解决消息的重复消费问题

1.MQ出现重复消费的场景1)提供者给MQ发送消息2)消费者1拉取这个消息(消息状态为待应答)3)消费者1把这个消息转成数据库的一条记录4)手动ack(网络出现故障,消费者和MQServer断开,断开后channel也就关闭了,消息状态变为待分配)5)MQServer接着把这个消息,发送给消费者2,消费者2接着消费就是重复消费
2.消息确认机制(Acknowlege)。当消费者获取消息后,会向RabbitMQ发送回执ACK,告知消息已经被接收。自动ACK:消息一旦被接收,消费者自动发送ACK手动ACK:消息接收后,不会发送ACK,需要手动调用,RabbitMQ就会把消息从队列中删除。
3.如何解决重复消费的问题1)给每个消息分配的一个全局的id,记录这个消息的消费状态2)消费者拿到这个消息后先判断这和消息是否已经被消费过3)消费完成后把这个消息的状态记录在redis中

4.RabbitMQ中有哪些组件?

1.MQServer
2.VirtualHost:虚拟主机
3.Exchange
4.Queue
5.Routing:路由器
6.Channel:信道(信道断开后,待应答的消息全部变成待分配)
7.Binding :路由和交换机的绑定

5.RabbitMQ的工作模式

1.简单模式
a)一个提供者,一个队列,一个消费者
b)一个发送消费,一个消费信息
2.工作模式
a)一个提供这个,一个队列,两个消费者
b)加快MQ消费速度
3.发布订阅
a)一个提供这个,一个交换机,一个队列,两个消费者
b)交换机把消息广播给所有的队列,每个队列都有一个消费者4.路由键
a)一个提供这个,一个交换机,一个路由键,两个队列,两个消费者5.主题模式
a)一个提供这个,一个交换机,一个路由键,两个队列,两个消费者
b) 关键词 : * :匹配一个  #: 匹配多个

6.如何保证RabbitMQ消息的可靠传输?

生产者丢失消息:开启事务,然后发送消息,如果发送过程中出现什么异常,事务就会回滚

消息队列丢数据:消息持久化

  1. 将queue的持久化标识durable设置为true,则代表是一个持久的队列
  2. 发送消息的时候将deliveryMode=2

消费者丢失消息:消费者丢数据一般是因为采用了自动确认消息模式,改为手动确认消息即可

cookie

本质是一小段的文本信息,格式的字典,key=value

会话cookie:保存在内存中,当浏览器的会话关闭时自动消失

持久cookie: 保存在硬盘中,只有失效时间到了,会自动消失

格式:(name,value值,Domain:域名,Path:路径,expries 失效时间)

cookie传输原理:

1.客户端第一次请求是,服务器产生cookie,通过响应头里面的set-Cookie把cookie传给客户端

2.当客户端第二次请求一直到后面的所有请求,在请求头的Cookie都会带上以上的Cookie信息,从而实现鉴权

Session

保存一些重要信息数据在服务器,通过cookie传给客户端,生命周期默认30分钟

Session鉴权原理

当客户端第一次登陆服务器时,服务器就会产生session, 还有sessionId, cookie响应给客户端时,会携带此次创建session的sessionId,用户再请求时,通过比对sessionId,就知道用户是否有访问权限

Token

1.登录之后自动生成

2.通过一个特定的获取token的接口获取token,通过appid和secret

然后后面的每一次请求都必须带上token实现鉴权,

加密方式: MD5,SHA系列 BCryptPasswordEncoder密码加密对象

access_token: 时效15分钟-2小时

refresh——token:时效15天

cookie与session与token 相同点与区别:

相同点: 都用于身份验证鉴权,都是服务器产生

q区别:

1.cookie保存在客户端,seesion存贮在服务器

2.session保存在服务器,生命周期默认30分钟

3.token是保存在服务器的数据库里面,持久

将对象转换为json

        //2.将对象转换为json//Gson-->toJson  (需要自己找依赖)//fastjson-->JSON (spring-cloud-starter-alibaba-sentinel)//jackson-->writeValueAsString (spring-boot-starter-web)String jsonStr=new ObjectMapper().writeValueAsString(object);

JWT令牌

JWT是用于微服务之间传递用户信息的一段加密字符串,该字符串是一个JSON格式,各个微服务可以根据JWT识别用户身份信息,保存用户信息到客户端,JWT令牌生成采用非对称加密算法

JWT令牌由三部分组成

Header头部: 令牌的类型(即JWT)及使用的签名算法 , 加密方式:Base64,可解密

Payload负载:1.标准中的注册声明 2.公共的声明(不参与令牌校验)3.私有声明(不参与令牌校验)

​ 加密方式:Base64,可解密

Signature签名 : header (base64后的)+payload (base64后的)+secret(秘钥)->加密:采用头部指定算法进行加密->密文->签名

鉴权的主要作用在签名中,网关中会有secret(秘钥)与传输来JWT中的Header和Payload加密,再与签名比对,以此判断jwt是否被篡改

用于防止jwt内容被篡改

项目中用户登录令牌的实现流程

  1. 用Bcrypassword.checkpw方法,判断用户的密码与数据库的是否一致
  2. 创建用户令牌信息用HashMap封装 生成的Jwt令牌Jwts.builder()
  3. 把Jwt令牌封装在cookie中,添加response中
  4. 返回登录成功的RESULT 和 token

实现流程:

​ 1.Spring以封装好,sca-auth认证授权服务,添加Oauth2 依赖,启动时,会返回一个默认的密码

​ 2.修改SecurityConfig配置类,添加登录成功或失败的处理逻辑,

​ 3.实现 UserDetailsService 获取用户详细信息的接口,用来与数据库中的用户信息作对比,认证是否正确,可否授权

​ 4.网关的配置中 Path=/auth/login/ 设置请求路径设计

 5. 构建令牌配置对象,JWT(Json Web Token-是一种json格式)方式将用户信息转换为json格式,然后进行加密,保存用户信息到客户端,客户端接收到这个JWT之后,保存在客户端,之后带着JWT访问其它模块时,资源服务器解析获得用户信息,进行访问,达到解放内存的目的6.  资源服务器配置,因为在认证授权服务器中已生成令牌token,此时,用户已携带此token来访问资源服务器, 资源服务器,要校验用户的token,是否合法,是否有效,所以在资源服务器中需要增加令牌配置7. 在ResourceController的上传方法上添加 @PreAuthorize(“hasAuthority(‘sys:res:create’)”)注解,用于告诉底层框架方法此方法需要具备的权限

Nginx

实现负载均衡,占有内存少不超过2M,并发能力强 5万/秒并发能力 实测: 2-3万/秒

反向代理

\1. 用户向代理服务器发送请求,(以为代理服务器就是真实目标服务器)
\2. 代理服务器接收请求时,根据自己的映射文件,重新发起新的请求 访问真实的目标服务器.
\3. 根据映射路径,查找真实的服务器资源.
\4. 获取资源返回给代理服务器.
\5. 代理服务器将资源交换给用户.

限流

漏桶算法

1.控制速率 2.控制并发数量

nginx.conf 限流配置



网关

作用

  • 安全,提供了统一的访问入口,降低了服务器受攻击面积
  • 提供了统一跨域解决方案
  • 提供了统一日志记录操作,可以进行统一监控
  • 提供统一的权限认证支持(校验token)
  • 提供了微服务限流功能,可以保护微服务,防止雪崩效应发生
  • 最主要作用整合各个微服务功能,形成一套或者多套系统

Nginx (tengine x) 是一个高性能的HTTP和反向代理web服务器,最外层流量拦截,抗高并发,耗时少,稳定,默认端口80

spring-cloud-gateway, 是spring 出品的 基于spring 的网关项目,集成断路器,路径重写,性能比Zuul好。

微服务网关做路由功能,整合各大微服务形成一套系统

spring:application:name: sca-gatewaycloud:gateway:globalcors:  #全局配置cors-configurations:'[/**]': # 匹配所有请求allowedOrigins: "*" #跨域处理 允许所有的域allowedMethods: # 支持的方法- GET- POST- PUT- DELETEroutes: #配置网关路由规则 ,可接下来配置与其他微服务的路由规则,哪些路径转发到哪些微服务- id: route01  #路由id,自己指定一个唯一值即可#uri: http://localhost:8081/      #网关帮我们转发的urluri: lb://sca-provider # lb为服务前缀(负载均衡loadbalance单词的缩写) +微服务名称predicates: ###断言(谓此):匹配请求规则- Path=/nacos/provider/echo/**  #请求路径定义,此路径对应uri中的资源filters: ##网关过滤器,用于对谓词中的内容进行判断分析以及处理- StripPrefix=1 #转发之前去掉path中第一层路径,例如nacos#- PrefixPath=/brand #转发之前加上path中第一层路径 /brand
logging: #日志打开到debuglevel:org.springframework.cloud.gateway: debug

网关负载均衡

网关是所有微服务访问的入口,并发量较大的时候,我们需要根据服务server Id的名称判断来做负载均衡操作。

如果Gateway Handler Mapping 通过断言predicates(predicates)的集合确定请求与路由(Routers)匹配,则将其发送到Gateway Web Handler。 Gateway Web Handler 通过确定的路由中所配置的过滤器集合链式调用过滤器,通过底层调用Ribbon 使用 服务名 去查找具体的服务实例

网关限流

项目中,有两层网关,第一层是nginx,主要是针对大量请求,流量的抵御,这时候它所释放的到微服务网关的流量是比较大的,第二层通过网关做限流,控制到每个微服务的流量,可以对每个服务起到保护的作用

限流算法

令牌算法 :1.匀速生成令牌存入到令牌桶中->Redis 5/s

漏桶算法:nginx运用

计数算法:

项目中 spring cloud gateway 默认使用redis的RateLimter限流算法来实现,定义KeyResolver用于计算某一个类型的限流的KEY也就是说,可以通过KeyResolver来指定限流的Key。

我们可以根据IP来限流,每个IP每秒钟只能请求一次

Sentienl

还可以结合Sentinel限流,

1.添加依赖,alibaba-sentinel 、alibaba-sentinel-gateway

2.添加配置

sentinel:transport:dashboard: localhost:8180 #Sentinel 控制台地址port: 8719 #客户端监控API的端口eager: true  #取消Sentinel控制台懒加载,即项目启动即连接

3.其限流的类型有几种?(两种-route id,api)

4.Sentinel底层限流的算法有哪些?(滑动窗口,令牌桶,漏斗

5.限流:系统能够承受的访问量进来,超出的会被丢弃。限流则从用户访问压力的角度来考虑如何应对故障

​ 熔断:比如A服务的X功能依赖B服务的某个接口,当B服务接口响应很慢时,A服务X功能的响应也会被拖慢,即A服务不在请求B这个接口,A服务内部发现B接口就直接返回错误,熔断的目的是应对外部系统的故障。

​ 降级:系统将某些不重要的业务或接口的功能降低,可以提供核心主业务服务功能,降级是应对系统自身的故障

Feign

调用步骤

1.添加了 Spring Cloud OpenFeign 的依赖
2.在 SpringBoot 启动类上添加了注解 @EnableFeignCleints
3.按照 Feign 的规则定义接口 DemoService, 添加@FeignClient 注解
4.在需要使用 Feign 接口 DemoService 的地方, 直接利用@Autowire 进行注入
5.使用接口完成对服务端的调用

工作原理:

1.SpringBoot 应用启动时, 由针对 @EnableFeignClient 触发程序扫描 classPath中所有被@FeignClient 注解的类, 由系统底层创建DemoService接口实现类(JDK代理类,虚假的实现类代理),并构建类的对象,然后交给spring管理

2.当对DemoService接口实现类调用时,都被转交给 Feign 框架, 翻译成 HTTP 的形式发送出去, 并得到返回结果, 再翻译回接口定义的返回值形式。

项目介绍

1.宠宝购物商城是基于springboot框架和springcloud组件开发的一款B2C电商模式

2.运营商把自家的产品发布到网站上,用户注册登录便可选购宠物相关的产品

3.主要由用户管理系统、商品系统、订单系统、广告系统、秒杀系统、支付系统、购物车系统、后台管理系统组成。

4.系统登录使用jwt令牌的单点登录系统,支持spring Oauth2.0协议,部分服务系统需验证用户携带token,及权限,提供相应的服务

采用MYSQL做持久化存储,REDIS做分布式锁保证订单与库存,使用分布式事务Seata AT模式控制各服务间数据一致性

登录

采用了BCryptPasswordEncoder进行加密,需要将资料中的BCrypt导入到common工程中,其中BCrypt.checkpw(“明文”,“密文”)用于对比密码是否一致。

JWT令牌

JWT是用于微服务之间传递用户信息的一段JSON格式的加密字符串,各个微服务可以根据JWT识别用户身份信息,保存用户信息到客户端,JWT令牌生成采用非对称加密算法

JWT令牌由三部分组成

Header头部: 令牌的类型(即JWT)及使用的签名算法 , 加密方式:Base64,可解密

Payload负载:1.标准中的注册声明 (颁发令牌的信息,签发者,过期时间等等)2.公共的声明(不参与令牌校验)3.私有声明(不参与令牌校验)

​ 加密方式:1.+2.+3. 进行 Base64加密, 可解密

Signature签名 : header (base64后的)+payload (base64后的)+secret(秘钥)->加密:采用头部指定算法进行加密->密文->签名

鉴权的主要作用在签名中,网关中会有secret(秘钥)与传输来JWT中的Header和Payload加密,再与签名比对,以此判断jwt是否被篡改

用于防止jwt内容被篡改

项目中用户登录令牌的实现流程

  1. 用Bcrypassword.checkpw方法,判断用户的密码与数据库的是否一致
  2. 创建用户令牌信息用HashMap封装 生成的Jwt令牌Jwts.builder()
  3. 把Jwt令牌封装在cookie中,添加response中
  4. 返回登录成功的RESULT 和 token

网关鉴权

定义全局过滤器,接收请求request中获取 到令牌的值并解析,解析成功说明令牌有效,方便后面其他服务先把从cookie中的token挪到 请求头 再可放行

单点登录-Spring security Oauth2

用户在其中任何一个站点登录后,可以免登录访问其他所有站点。

Spring Security 是什么?(spring框架中的一个安全默认,实现了认证和授权操作)

OAUTH协议

最主要是解决认证协议的通用标准问题,因为要实现跨系统认证,各系统之间要遵循一定的
接口协议。

oauth2定义了一种认证授权协议,一种规范,此规范中定义了四种类型的角色:

1)资源拥有者(User)
2)认证授权服务器(jt-auth)
3)资源服务器(jt-resource)
4)客户端应用(jt-ui)
同时,在这种协议中规定了认证授权时的几种模式:
1)密码模式 (基于用户名和密码进行认证)
2)授权码模式(就是我们说的三方认证:QQ,微信,微博,。。。。)
3)隐式授权模式(Implicit)
4)客户端模式(Client Credentials)

1、用户请求认证服务完成认证。

2、认证服务下发用户身份令牌,拥有身份令牌表示身份合法。

3、用户携带令牌请求资源服务,请求资源服务必先经过网关。

4、网关校验用户身份令牌的合法,不合法表示用户没有登录,如果合法则放行继续访问。

5、资源服务获取令牌,根据令牌完成授权。

6、资源服务完成授权则响应资源信息。

公钥私钥

非对称加密算法RSA生成的, 公钥加密(各个服务可以校验私钥信息),私钥解密(授权服务)

Keytool 是一个java提供的证书管理工具 ,每个证书包含公钥和私钥 ,openssl是一个加解密工具包(要下载)

1.在一个文件下cmd执行Keytool 命令生成changgou.jks证书-> 2.在changgou.jks所在目录执行指令导出公钥->3.公钥拷贝到文本public.key文件中,合并为一行->4.将它放到需要实现授权认证的工程

根据私钥生成jwt令牌

根据创建证书路径,创建秘钥工厂,获取私钥—>定义Payload,生成Jwt令牌

根据公钥解析令牌

提供令牌,对公钥RSA算法的对象 给 JwtHelper来解析校验

项目中在定义全局过滤器中判断token有效,鉴权

  1. 获取用户令牌信息 (1)头文件(2)参数(3)cookie
  2. 如果没令牌,则拦截,如果有,检验是否有效(解析token,前缀是否有bearer,没有帮加上),无效也拦截
  3. 将令牌封装到头文件中,方便为检验用户spring Oauthor2.0 是否有授权认证
  4. 有效放行chain.filter()

商品表结构介绍

sku

同款商品所独有属性字段

spu

同款商品所共有的属性的抽取

购物车

只是目前临时存储数据到Redis,等用户下单后才将数据从Redis取出存入到MySQL中。

先校验用户的权限,并校验令牌

登录认证

资源服务器授权配置

1.将公钥拷贝到 public.key文件中,将此文件拷贝到每一个需要的资源服务工程的classpath下

2.添加依赖 spring-cloud-starter-oauth2

3.写一个配置类,配置此系统的Http请求路径安全控制策略(就是哪些路径需要校验,哪些路径可以跳过校验像注册)以及读取公钥信息识别令牌

@Configuration // 配置类

@EnableResourceServer //开启资源服务器校验->令牌校验

@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)

//激活方法上的@PreAuthorize注解

以上配置完后,必须携带有效token访问此资源服务器

访问认证服务器中,UserDetailsServiceImpl中会查询数据库核实用户的身份信息,及所拥有权限

在资源服务器的具体执行方法上定义相应权限@PreAuthorize(身份,或者权限)可访问

把 订单 存储在Redis 采用 hash类型 结构 ,因为一个用户就一个购物车,不能重复,用key是 userId,而且其他结构每次查询购物车中的商品需要遍历

key是 userId(namespace) :

->key1商品ID, CatOItem(name,图片,数量,price,等)

->key2商品ID, CatItem(name,图片,数量,price,等)

->key3 商品ID, CatItem(name,图片,数量,price,等)

加入购物车

实现步骤:

加入购物车:

1.获取加入商品CartItem和userID作为参数

2.查询商品详情,使用openfeign调用skuFeign和spufeign

3.先查询userID的redis购物车,在购物车中是否商品id,有就改变数量就行,没有就新增

3.把用户要添加的商品封装在CatItem

4.采用 hash类型存入redis key: cat_username put (商品id,CatItem)

查询购物车列表:

1.查询userID,有购物车?没有就返回空。有就查询

2.获取redist 的key :cat_username 所有 的value (redisTemplate.boundHashOps(“Cart”+username))

当添加购物车里的商品数量<=0,需要移除该商品信息 delete(id)

当购物车没商品,移除购物车,判断key :cat_username 的size==0,delete


用户要想将商品加入购物车,必须得先登录授权,登录授权后再经过微服务网关,微服务网关需要过滤判断用户请求是否存在令牌,如果存在令牌,才能再次访问微服务,此时网关会通过过滤器将令牌数据再次存入到头文件中,然后访问模板渲染服务,模板渲染服务再调用订单购物车微服务,此时也需要将令牌数据存入到头文件中,将令牌数据传递给购物车订单微服务,到了购物车订单微服务的时候,此时微服务需要校验令牌数据,如果令牌正确,才能使用购物车功能,并解析令牌数据获取用户信息。

微服务间调用的令牌认证(令牌的传递)

因为微服务之间并没有传递头文件,所以我们可以定义一个拦截器,每次微服务调用之前都先检查下头文件,将请求的头文件中的令牌数据再放入到header中,再调用其他微服务即可。

public class FeignInterceptor implements RequestInterceptor {@Overridepublic void apply(RequestTemplate requestTemplate) {try {//使用RequestContextHolder工具获取request相关变量,//用户当前用户请求的所有数据,包含请求头,和请求参数等//用户当前请求的时候对应线程的数据,ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();if (attributes != null) {//取出requestHttpServletRequest request = attributes.getRequest();//获取所有头文件信息的keyEnumeration<String> headerNames = request.getHeaderNames();if (headerNames != null) {while (headerNames.hasMoreElements()) {//头文件的keyString name = headerNames.nextElement();//头文件的valueString values = request.getHeader(name);//将令牌数据添加到头文件中requestTemplate.header(name, values);}}}} catch (Exception e) {e.printStackTrace();}}
}

项目最大困难

问题:

服务间使用feign调用时,会报Feign调用无效异常,debug获取当前线程请求的数据为空,很奇怪

原因:

feign配置开启熔断的是当前线程,默认是线程池隔离,会开启新的线程,

解决:

需要将熔断策略换成信号量隔离,此时不会开启新的线程,熔断策略strategy: SEMAPHORE

#开启Feign的熔断:默认是线程池隔离
feign:hystrix:enable: true
#hystrix 配置 信号量隔离
hystrix:command:default:execution:isolation:thread:timeoutInMilliseconds: 10000strategy: SEMAPHORE

订单系统

添加订单

订单表

CREATE TABLE `tb_order` (`id` varchar(50) COLLATE utf8_bin NOT NULL COMMENT '订单id',`total_num` int(11) DEFAULT NULL COMMENT '数量合计',`total_money` int(11) DEFAULT NULL COMMENT '金额合计',`pre_money` int(11) DEFAULT NULL COMMENT '优惠金额',`post_fee` int(11) DEFAULT NULL COMMENT '邮费',`pay_money` int(11) DEFAULT NULL COMMENT '实付金额',`pay_type` varchar(1) COLLATE utf8_bin DEFAULT NULL COMMENT '支付类型,1、在线支付、0 货到付款',`create_time` datetime DEFAULT NULL COMMENT '订单创建时间',`update_time` datetime DEFAULT NULL COMMENT '订单更新时间',`pay_time` datetime DEFAULT NULL COMMENT '付款时间',`consign_time` datetime DEFAULT NULL COMMENT '发货时间',`end_time` datetime DEFAULT NULL COMMENT '交易完成时间',`close_time` datetime DEFAULT NULL COMMENT '交易关闭时间',`shipping_name` varchar(20) COLLATE utf8_bin DEFAULT NULL COMMENT '物流名称',`shipping_code` varchar(20) COLLATE utf8_bin DEFAULT NULL COMMENT '物流单号',`username` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '用户名称',`buyer_message` varchar(1000) COLLATE utf8_bin DEFAULT NULL COMMENT '买家留言',`buyer_rate` char(1) COLLATE utf8_bin DEFAULT NULL COMMENT '是否评价',`receiver_contact` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '收货人',`receiver_mobile` varchar(12) COLLATE utf8_bin DEFAULT NULL COMMENT '收货人手机',`receiver_address` varchar(200) COLLATE utf8_bin DEFAULT NULL COMMENT '收货人地址',`source_type` char(1) COLLATE utf8_bin DEFAULT NULL COMMENT '订单来源:1:web,2:app,3:微信公众号,4:微信小程序  5 H5手机页面',`transaction_id` varchar(30) COLLATE utf8_bin DEFAULT NULL COMMENT '交易流水号',`order_status` char(1) COLLATE utf8_bin DEFAULT NULL COMMENT '订单状态,0:未完成,1:已完成,2:已退货',`pay_status` char(1) COLLATE utf8_bin DEFAULT NULL COMMENT '支付状态,0:未支付,1:已支付,2:支付失败',`consign_status` char(1) COLLATE utf8_bin DEFAULT NULL COMMENT '发货状态,0:未发货,1:已发货,2:已收货',`is_delete` char(1) COLLATE utf8_bin DEFAULT NULL COMMENT '是否删除',PRIMARY KEY (`id`),KEY `create_time` (`create_time`),KEY `status` (`order_status`),KEY `payment_type` (`pay_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

订单详情表

REATE TABLE `tb_order_item` (`id` varchar(50) COLLATE utf8_bin NOT NULL COMMENT 'ID',`category_id1` int(11) DEFAULT NULL COMMENT '1级分类',`category_id2` int(11) DEFAULT NULL COMMENT '2级分类',`category_id3` int(11) DEFAULT NULL COMMENT '3级分类',`spu_id` varchar(20) COLLATE utf8_bin DEFAULT NULL COMMENT 'SPU_ID',`sku_id` bigint(20) NOT NULL COMMENT 'SKU_ID',`order_id` bigint(20) NOT NULL COMMENT '订单ID',`name` varchar(200) COLLATE utf8_bin DEFAULT NULL COMMENT '商品名称',`price` int(20) DEFAULT NULL COMMENT '单价',`num` int(10) DEFAULT NULL COMMENT '数量',`money` int(20) DEFAULT NULL COMMENT '总金额',`pay_money` int(11) DEFAULT NULL COMMENT '实付金额',`image` varchar(200) COLLATE utf8_bin DEFAULT NULL COMMENT '图片地址',`weight` int(11) DEFAULT NULL COMMENT '重量',`post_fee` int(11) DEFAULT NULL COMMENT '运费',`is_return` char(1) COLLATE utf8_bin DEFAULT NULL COMMENT '是否退货,0:未退货,1:已退货',PRIMARY KEY (`id`),KEY `item_id` (`sku_id`),KEY `order_id` (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
情景 支付状态(0未支付1支付2退款中3已退款) 发货状态(0未发货1已发货2已收货) 是否删除(0,1) 订单状态(0 未完成 1完成 2退货中3已退货) 评价信息
下订单未支付 0未支付 未发货 1 0未完成
下订单未支付 1支付 未发货 1 1完成
发货 1支付 发货 1 1完成
收货 1支付 收货 1 1完成 0
退货中 2退款中 0未发货 1 2退货中
退货中 2退款中 1发货 1 2退货中
收到退货 3已退款 2已收货 1 3退货
0

从购物车中下订单

  1. 从token中获取userId,设置给order
  2. 订单ID生成,采用Idwork,雪花算花,
  3. 在购物车中列一个字段属性 封装购物车中的被勾选的商品id集合,遍历查询对应购物车的商品添加到新建集合OrderItems订单明细表中,
  4. 订单的属性: 订单号,订单状态,收货人,收货地址,收获联系方式,商品属性,商品数量,商品单价,下单时间,支付时间,发货时间,收货时间
  5. 遍历OrderItems订单明细中的商品添加属性(购买商品总数量 ,总金额,实付金额)到OrderItem订单中
  6. 提交订单后,从购物车中移除已经提交的商品,并调用商品系统微服务 减少相应商品的库存

解决超卖问题

方案一:

Redis 中setnx 命令是对key设置分布式锁 : 如果key (商品id)不存在的时候,就把key设置成value(UUID,当作锁的标示),若key存在就不做改变(注意:对key (商品id)设置生效时间,以防redis宕机死锁,到时间自动释放)

try{

获取库存,-1

}finally{

高并发的情况会发生超出锁的有效时间自动释放当前锁,而在这个位置释放了 后面获取这把锁线程 , 导致最开始的商品的锁 ,死锁,给锁做标记uuid(value),判断当前的value.equals(get(key)){

释放锁,以防死锁,删除key

}

}

方案二: 可以解决方案一的最开始因系统压力,运行时间超有效时间发生的死锁问题

使用Redission 分布式锁,是多个Redission线程依次给key (商品id)加锁,但是只能加一个锁,其他Redission线程会自循环判断key (商品id)的锁是否释放,释放了才可以再加一个锁,其中,Redission线程,会执行一个分线程,判断每隔 1/3的有效时间 是否还有锁,如果有给锁延长时间,在finally最后手动释放锁

redissionlock.lock(30s)

try{

获取库存,-1

}finally{

redissionlock.unlock()

释放锁,以防死锁,

}

}

zookeepr可以解决 redis主从架构的宕机问题,但是性能不如Redis

发送 -》延时队列30分钟(死信交换机,死信队列)–》队列(监听)

死信队列:过了一定的时间,有效期过了,但数据并没有被读取过,

秒杀系统

宠宝购物购物车+订单相关推荐

  1. SSH框架实现仿淘宝购物demo

    还记得六月份实习的时候,以前做过一个电商的项目.项目里面须要实现相似淘宝购物车的移动端的demo.随着项目的进行,再一次跟购物车碰面,可是今天呢,不是移动端的需求.怎样使用SSH框架实现相似淘宝的购物 ...

  2. python淘宝_python实现淘宝购物系统

    本文实例为大家分享了python淘宝购物系统的具体代码,供大家参考,具体内容如下 代码如下: #刚创建账户所拥有的钱 money = 0 #定义商品列表 goods_list = [ {'name': ...

  3. 弘辽科技:淘宝订单编号会透露个人信息吗?淘宝如何查看订单编号

    在淘宝平台上每成交一个订单都会有对应的订单信息和订单编号,那么有一些朋友在淘宝平台上下单购物的时候,有非常强的安全意识,所以想要确认一个问题就是这个淘宝订单编号会透露个人信息吗? 会. 淘宝订单编号即 ...

  4. auto.js实现淘宝快速提交订单

    @[TOC] (淘宝快速提交订单) 博主是新手一枚,(第一次使用也是第一次发布博客哈哈哈)闲暇之余用auto.js写了一个淘宝快速提交订单的小脚本,(本脚本适用于xxx前xx名付款者免单之类的用途), ...

  5. 2010年,我发现了淘宝购物省钱的秘密

    每个人在今天谈到网购,谈到淘宝,应该都不会陌生吧,互联网的普及给现在人类带来的翻天覆地的变化,大家也顺潮性的喜欢网购,网购的快捷,方便使得每年淘宝的交易量都大大提升,在这个亚洲最大的C2C平台,使一切 ...

  6. BootStrap-书籍搜索列表购物车订单结算form表单分页图标

    目录 1. 用BootStrap实现案例 1.1 搜索列表 1.2 购物车&订单结算 1.3 form表单&分页&图标 1. 用BootStrap实现案例 1.1 搜索列表 实 ...

  7. javah5仿淘宝购物系统计算机毕业设计MyBatis+系统+LW文档+源码+调试部署

    javah5仿淘宝购物系统计算机毕业设计MyBatis+系统+LW文档+源码+调试部署 javah5仿淘宝购物系统计算机毕业设计MyBatis+系统+LW文档+源码+调试部署 本源码技术栈: 项目架构 ...

  8. 使用selenium进行淘宝购物测试

    文章目录 前言 一.登录滑块验证 二.搜索 三.跳转新窗口 前言 使用selenium进行淘宝购物测试 一.登录滑块验证 直接说结论:别用密码了,直接手动扫码登录 淘宝检测到selenium后你就没办 ...

  9. 数据库课程设计·淘宝购物系统

    数据库大作业·淘宝购物系统 对接支付宝网站支付·仅支持PC端 在线体验地址:https://mysql.cxyepoch.cn 1.前台: ①商品列表可通过左右隐藏按钮进行轮换. ②用户未登陆时显示未 ...

最新文章

  1. Docker Swarm删除节点
  2. Matlab:成功解决 Inner matrix dimension must agree
  3. 科大星云诗社动态20210322
  4. 后缀数组--可重叠的K次最长重复子串(POJ3261)
  5. django 轮播图上传_django之动态轮播图技术的实现
  6. 利用伸展树提高区间操作的性能
  7. 面向对象编程(OOP)特性 类和对象
  8. python写机器人程序_从Python写入机器人框架控制台
  9. mapper接口中的方法,example实例解析
  10. 深圳市科技创新委员会关于2021年高新技术企业培育库拟入库企业名单公示的通知
  11. Codeforces Round#767(Div.2) F1. Game on Sum (Easy Version)
  12. IOUtils使用介绍
  13. java反编译luyten使用
  14. 密码学 SM3算法 Python实现
  15. 大批量数据导出到Excel的实现
  16. 查看视频文件格式信息的工具--MediaInfo
  17. repo sync repo reset: error: entry ‘comand.py ‘ not uptodate . cannot merge
  18. 算法面试准备建议|面试官角度
  19. 达梦数据库巡检脚本--生成html格式的报告
  20. RabbitMq报错 Execution of Rabbit message listener failed

热门文章

  1. react项目启动报错”无法使用 JSX,除非提供了 “--jsx“ 标志。ts(17004)“
  2. Word2016多行公式在等号处对齐、自动编号和引用、公式居中且编号右对齐
  3. 茶语清心 名家说茶名句
  4. 【EtherCAT实践篇】一、TwinCAT3安装
  5. 华三 IRF的相关配置和注意事项。
  6. 【动态规划百题强化计划】1~10
  7. C/C++ 控制台输出彩色文本(改变局部字体的颜色)
  8. Mac上如何设置使用触发角快速启动屏幕保护程序
  9. 计算机有游戏吗,这些容量最大的游戏,你的电脑上都有吗?
  10. LeetCode刷题专栏第一篇--思维导图时间安排