下单业务可能会出现的问题:

1.超卖

2.数据一致性

3.超时

4.性能

业务流程图绘制:

![lcl](C:\Users\28168\Pictures\Saved Pictures\UI10.31\lcl.png)

问题解决

下面我们一一解决上面提出的订单业务的四个问题

1.超卖问题

对于超卖问题,这里我采用了Redission分布式锁来解决,通过Redission锁定库存,从而避免了超卖问题

锁定库存的业务流程

hhh

什么是Redission?

Redisson分布式锁解决分布式环境下并发安全问题,完全实现了juc的功能,不仅有锁,还都是分布式锁

Redisson是架设在Redis基础上的一个Java驻内存数据网格(ln-Memory Data Grid)。

Redisson在基于NIO的Netty框架上,充分的利用了Redis键值数据库提供的一系列优势,在java实用工具包中常用接口的基础上,为使用者提供了一系列具有分布式特性的常用工具类。使得原本作为协调单机多线程并发程序的工具包获得了协调分布式多机多线程并发系统的能力,大大降低了设计和研发大规模分布式系统的难度。同时结合各富特色的分布式服务,更进一步简化了分布式环境中程序相互之间的协作。

使用步骤

1.添加Redission依赖

2.编写工具类来生成Redission client(直接参照官方配置)

其中工具类中提供获取分布式锁的方法

//基于Redisson的分布式锁
public static RLock getLock(String key){
return client.getLock(key);
}

3.业务代码中使用

RLock rLock=RedissonUtils.getLock(RedisKeyConfig.COUPON_LOCK+ctid); //先获取订单id
try{
//尝试获取分布式锁:超时时间和时间单位
if(rLock.tryLock(10,TimeUnit.SECONDS)){
//获取锁成功成功,就继续执行业务逻辑
//。。。
}else{
//获取锁失败,直接返回领取失败
return RUtil.fail("亲,没有了!);
}
}catch (InterruptedException e){
e.printstackTrace();
return RUtil.fail("亲,系统故障!");
}finally{
rLock.unlock();
}

2.数据一致性问题

这里涉及到分布式事务,就需要用到分布式事务,我用到的是seata

  1. seata的XA模式,CP,需要互相等待各个分支事务提交,可以保证强一致性,性能差
  2. seata的AT模式,AP,底层使用undo log实现,性能好
  3. seata的TCC模式,AP,性能较好,不过需要人工编码实现
  4. MQ模式实现分布式事务,在A服务写数据的时候,需要在同一个事务内发送消息到另外一个事务,异步,性能最好

3.超时问题

超时订单处理流程如业务流程图所示。

当下单完成后生成订单会存储到redis,接着会扔到MQ交换机里,MQ交换机里有两个队列,一个是数据同步队列,一个是死信队列,数据同步队列作用是消费者同步数据库,而死信队列是没有消费者的,死信队列会设置一过期时间(对应着订单的超时时间),超时之后会被投递到死信交换机,死信交换机中有一个延迟队列,到达延迟队列的消息一定是超时了的,延迟队列有消费者,这个消费者负责检查是不是没有付款,如果没有付款就取消订单,同时释放库存

MQ使用步骤

1.引入依赖

2.RabbitMQConfig的配置(创建需要的三个队列,创建交换机,创建绑定)

3.发送的业务流程(可使用rabbitTemplate)

4。接收方业务流程(在类上使用@RabbitLister(queues=”队列名称”)指定要监听的队列名称,然后在要监听的方法hander上加上注解@RabbitHandler)

4.性能问题

可以使用MQ的削峰填谷