五,实现订单延迟关闭
业务场景:超过30分钟未付款的订单自动关闭,这个功能应该怎么实现?
RabbitMQ本身不支持延迟投递,总的来说有2种实现方案:
1,先存储到数据库,用定时任务扫描
(定时任务比较容易实现,比如每搁1分钟扫描一次,查出30分钟之前未付款的订单,把状态改为关闭。但是如果数据量过大,比如:10万条,把这些全部的数据查询到内存中逐条处理,也会给服务器带来很大的压力,影响正常的业务运行)
2,利用RabbitMQ的死信队列(Dead Letter Queue)实现
(借助RabbitMQ消息的特性),
(1)队列有一个消息过期属性,这个属性叫x-messge-ttl,所有队列中的消息超过时间未被消费时,都会过期。TTL(Time To Live)。
(2)RabbitMQ中消息的单独的过期时间
在发送消息的时候通过MessageProperities指定消息属性
问题:如果同时指定了msg TTL和Queue TTL,则小的那个时间生效。有了过期时间还不够,这个消息不能直接丢弃,不然就没办法消费了。最好是丢到一个容器里边,这样就可以实现延迟消费了。还需要用到死信队列
死信:消息过期以后,如果没有任何配置,是会直接丢弃的。我们可以通过配置让这样的消息变成死信(Dead Letter),在别的地方存储。
队列在创建的时候可以指定一个死信交换机DLX(Dead Letter Exchange)。死信交换机绑定的队列被称为死信队列DLQ(Dead Letter Queue),DLX实际上也是普通的交换机,DLQ也是普通的交换机(例如替补球员也是普通球员)。
也就是说如果消息过期了,队列制定了DLX,就会发送到DLX,如果DLX绑定了DLQ,就会路由到DLQ,路由到DLQ之后,我们就可以消费了。
死信队列的使用步骤:
总结一下:利用过期时间,过期之后投递到DLX ,路由到DLQ,监听DLQ,实现了延迟队列。
消息的流转流程:
生产者-原交换机-原队列(超过TTL之后)——死信交换机——死信队列——最终消费者。
Message消息在什么情况会变成死信?
(1)消息的时间过期
(1)消息被消费者拒绝并且未设置重回队列:(NACK||Reject)&&requeue==false
(2)队列达到最大长度,超过了Max Length(消息数)或者Max Length bytes(字节数) ,最先入队的消息会被发送到DLX。
3.用插件rabbitmq-delayed-messge-exchange
六,RabbitMQ的流量控制——控制服务端消息数量
服务端限流:
(1)内存控制
(2)磁盘控制
消费端限流:
六,消息可靠性
1代表消息从生产者发送到Broker? 如何确认?
Confirm确认模式