订单提交业务之在业务中谈mq

订单提交业务之在业务中谈mq

死信队列

  • 如果出现异常,不入队,丢入死信队列,此时不建议重试

定义

  • new queue的时候
  • arguments 作为一个hashmap可以装一些参数,
    • dead-letter-exchange
    • 同时也主要定义相应的队列
    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U42kULU6-1602987667725)(C:\Users\liusiping\AppData\Roaming\Typora\typora-user-images\image-20201018073540169.png)]
    • 同时也需要相应的死信交换机和绑定关系
    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OthsevpT-1602987667727)(C:\Users\liusiping\AppData\Roaming\Typora\typora-user-images\image-20201018073553755.png)]
    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JGCL24dw-1602987667728)(C:\Users\liusiping\AppData\Roaming\Typora\typora-user-images\image-20201018073500026.png)]

单条确认和多条确认

  • 把单条确认变成批量确认
  • 每一条消息和broker会有网络通信,当并发量很大,单条确认会有大量的网络通信,造成效率较低
  • 但是批量确认的缺点是有消息丢失
  • 此处可以通过结合死信队列来解决,但是也不是消息绝对不丢失

延迟队列

  • 延迟消费
  • 订单失效的业务场景
  • √ 通常场景:生成订单数据,未支付情况
    • 所以对每一笔订单需要有时效性,比如订单最多保存10分钟,
    • 定时任务10分钟一扫,时效性差,有比较大的误差
    • 通过mq解决,<1>生成订单数据。<2>往mq发送消息,某个队列,不是用来消费的,让里面的消息过期,可以指定这个队列里面的消息的过期时间,消息一旦过期就会插入到死信队列。<3>消费这个死信队列里面的消息,去判断数据库中的支付状态,反之,修改订单状态为取消,库存+1。

如何保证消息成功投递

  • 事务方式,太耗性能,效率低
  • comfire方式,不建议
    • config里面,confirmCallback
    • 当消息成功发送到echange
    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cXIjgAXa-1602987667730)(C:\Users\liusiping\AppData\Roaming\Typora\typora-user-images\image-20201018081351126.png)]
    • 没有成功时,发送到
    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hP4AM7Ze-1602987667731)(C:\Users\liusiping\AppData\Roaming\Typora\typora-user-images\image-20201018081423597.png)]
    • 所有的前提是需要在application.yml中配置开启
    • 存在的问题<1>broker和provider需要通信,影响吞度量。<2>不能100%投递,并且存在消息重复消费
  • 秒杀业务的订单提交
    • 允许丢失数据,但是库存少一了
  • 银行转账业务员、支付业务
    • 这种消息就要严格保证不能丢
    • 如何保证?<1>生产者这边必须要有消息存根。在往mq发送消息之前,先存mongdb,mysql做本地存根。消息的流水号。<2>需要有一个timer定时任务去扫mongodb,mysql状态没有成功的消费的记录有一次投递到mq。设计表时要设计发送次数限制,超过固定次数就不发送到mq了,避免mq被垃圾消息填满。<3>消费端需要去消费mq里的消息,这条消息一直消费不成功,没有办法回调去修改mysql,mongodb里面的消息状态,这时定时任务一直会发送垃圾消息到mq,导致mq的吞吐量下降。<4>消费端的重复消费,涉及到的就是幂等设计,消费者这端如果成功消费了消息,就需要有一个消息表存储消费成功的消息,如果有则说明之前已经成功消费,那么就不再消费了,如果没有则消费这条消息。<5>还有重复消费问题,ack失败了,(网络波动或者broker挂掉了),消息会存在 mq里面,又会被消费者重复消费,一样的要幂等设计。<6>完全人工的手动对账,手动补偿。生产者一直发送失败
    • 两张表,消息提交表(提交记录),成功消费消息表(幂等设计表)
    • 保证绝对的数据安全,性能方面一定会下降
  • 为什么要自研mq,因为mq都是与业务结合的,有自己的表模型

提交订单-去结算

submitOrder接口

  • 版本1
    • 设置订单有效时间,在redis里面,有效期3秒
    • 异步发送消息
    • 然后一个while(true)用来接收消费端反馈
  • 版本2
    • 生产者sendAndReciver reply-to消息反馈(reply队列)
    • 需要配置,需要有反馈
    • rabbitTemplate
    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dTwo99Vn-1602987667733)(C:\Users\liusiping\AppData\Roaming\Typora\typora-user-images\image-20201018094602065.png)]
    • 这是一个API方法
    • 消费者
    • process
    • 去消费reply-to队列里面的消息,必须要有返回值
    • 缺点,整个过程非常慢,吞吐量下降
  • 版本3
    • 与版本2的区别,不需要应答,但是要返回给前端
    • 预生成一个订单id,只发送不应答,保存订单数据到redis,然后把订单id返回给前端,
    • 前端去查询另一个查订单详情的接口,先查缓存,缓存没有,再去查数据库
    • 这里整个方法有一个try-catch,有一个redis弱脚本,如果mq投送失败,如果库存大于0,会去让库存+1

补偿

  • 1000台手机,瞬时秒杀,已经到0台了(弱脚本,不会到0)
  • 有5个人没支付,但是因为某些原因有1个人的库存补偿没有补偿进去
  • 如果执行到catch宕机了,补偿就失败了,所有可以在1000台的基础上有一个余量。

猜你喜欢

转载自blog.csdn.net/Markland_l/article/details/109141969