当一个队列中的消息满足下列情况之一时,可以成为死信(dead letter):
如果该队列配置了dead-letter-exchange属性,指定了一个交换机,那么队列中的死信就会投递到这个交换机中,而这个交换机称为死信交换机(Dead Letter Exchange,简称DLX)。
ATT:死信交换机实际上也就是一个普通的交换机,它能在任何队列被指定,只不过赋予了接受死信的功能而已。所以需要在定义队列时就指定死信交换机。
@Bean
public Queue ttlQueue(){
return QueueBuilder.durable("simple.queue")//指定队列名称并持久化
.ttl(10000)//设置队列的超时时间,10秒
.dealLetterExchange("dl.direct")//指定死信交换机
.build();
}
延迟队列:进入队列的消息会被延迟消费的队列
场景:超时订单、限时优惠、定时发布
延迟队列本质还是官方的三种交换机,只是添加了延迟功能。
实现延迟队列可以用以下两种方法之一:
RabbitMQ官方的插件社区地址为:https://www.rabbitmq.com/community-plugins.html
回答:(背熟以下回答,大概用时1min)
嗯,这个我们还真遇到过,是这样的,我们当时消费者是设置了自动确认机制,当服务还没来得及给MQ确认的时候,服务宕机了,导致服务重启之后,又消费了一次消息。这样就重复消费了
因为我们当时处理的支付(订单|业务唯一标识),它有一个业务的唯一标识,我们再处理消息时,先到数据库查询一下,这个数据是否存在,如果不存在,说明没有处理过,这个时候就可以正常处理这个消息了。如果已经存在这个数据了,就说明消息重复消费了,我们就不需要再消费了
面试官:那你还知道其他的解决方案吗?
候选人:
嗯,我想想~
其实这个就是典型的幂等的问题,比如,redis分布式锁、数据库的锁都是可以的。
回答:(背熟以下回答大概用时1min)
首先关于死信的定义,一般满足以下情况之一,就可能成为死信。譬如,过期时间到了却仍未被消费的消息,或者要投递的队列满了,最早的消息就可能成为死信。死信交换机实际上就是设置的一个用来接收死信的交换机,它与普通的交换机其实没有什么区别。
而延迟队列,一般用于超时订单、限时优惠、定时发布之类的场景。本质还是官方的三种交换机之一,只是添加了延迟功能。我们实现它可以有两种方式。第一种就相当于死信交换机加上TTL,第二种更简单一些,就是去官网下载相关的插件,然后定义时把delay设置为true即可。