订单服务支付流程
rabbitMQ实现30分钟后自动取消订单 消息
一、如何有效防止订单重复支付
核心:加锁 redis分布式锁
支付状态:未支付 支付中 已完成
1.缓存结果:支付申请成功、支付回调都应该缓存结果
2.再次申请支付时,先进入redis缓存查询订单状态
3.用户已经支付成功,重复再次支付要拒绝,如果用户上一笔支付状态属于支付中,我们应该取消支付中的流水,再发起支付
4.如果是用户通过不同的第三方进行重复支付或者平台不支持取消支付,可以允许用户重复支付,但是在支付回调结果时要查看redis缓存中,是否有已经支付成功的流水,发起退款操作
二、如何有效防止掉单
1.外部掉单:调用第三方支付服务后,没有及时返回支付回调结果,导致支付状态没有同步到商城,外部掉单
2.内部掉单:支付状态没有及时同步到订单服务,客户端没有及时获取支付状态,内部掉单
防止外部掉单:延迟队列,当用户发起支付流程之后,同时发起异步延时消息到MQ,如果消息超时,则主动查询数据中的支付状态,并主动调用第三方支付服务查询支付回调结果,如果是支付成功,则修改支付状态
防止内部掉单:同步+异步防止内部掉单
同步通知:当支付服务收到支付回调结果时,同时同步到订单服务,同步支付状态,如果程序发生故障,则可能导致支付状态同步失败
异步通知:当支付服务收到支付回调结果时,使用异步通知通知订单服务,订单服务利用MQ的消息中间件的重试机制来尽大可能来保证支付状态的同步
rabbitMQ避免消息重复消费
每条消息带一个唯一id
消费者:消费者获取到消息之后先查询redis缓存,查询消息是否存在,如果存在则已消费,丢弃消息,不存在则消费消息,消费成功后写入redis缓存
rabbitMQ避免消息丢失
生产者消息丢失
生产者将信道设置成确认模式(confirm 模式),信道进入确认模式之后,信道中的消息都会指派一个唯一id(从1开始),一旦消息被投递到匹配的队列之后就会返回确认通知给生产者,包括唯一id,这时生产者就会知道消息已经正确到达队列中
confirm 模式,发送方确认机制,会回调两次 生产者到交换机回调函数confirm,交换机路由队列失败时,会回调returnedMessage
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
消费者消息丢失
消费者获取消息之后会自动签收,签收之后队列中的消息会立即删除,假如消费者消费时发生故障,则消息会丢失,所以我们要把自动签收改成手动签收,当消息正常消费之后,手动签收返回给MQ,再删除队列中的消息
消费成功调用channel.basicAck(). 消费失败时调用channel.basicNack()告诉MQ,消息消费失败了
rabbitMQ如何保证消息消费顺序
一个队列多个消费者
一个队列对应一个消费者,同一个 queue 的消息是一定会保证有序的,那么同一个订单号的消息就只会被一个消费者顺序消费,从而保证了消息的顺序性
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
roueKey:消息发送到交换机需要指定路由key
bindIngKey:交换机转发消息到队列需要指定bindKey
当binding key 和routing key 相匹配时,消息会被转发到指定的队列中