订单提交业务之在业务中谈mq
其他
2021-02-11 10:20:16
阅读次数: 0
订单提交业务之在业务中谈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