消息队列——死信交换机
一、初识死信交换机:
1、什么是死信队列:
死信队列,英文缩写:DLX 。Dead Letter Exchange(死信交换机),当消息成为Dead message后,可以被重新发送到另一个交换机,这个交换机就是DLX。
在其他的MQ产品中,很多是没有交换机的概念的,在这些MQ产品中,死信队列就是Dead Letter Queue。在RabbitMQ中有交换机的概念,所以死信队列指的是死信交换机。
消息发送到交换机,交换机将消息路由到一个设置了过期时间的Queue,当消息没有在过期时间内被消费的时候,这个消息就会通过DLX重新发送到新的队列,进而被消费者消费。
2、消息什么时候会成为死信:
- 队列消息长度到达限制;也就是队列能存10条,但来了11条,第11条消息已经存不进去了,则最早的消息(第一条)则可能成为死信。
- 消费者拒接消费消息,basicNack/basicReject,并且不把消息重新放入原目标队列,requeue=false;
- 原队列存在消息过期设置,消息到达超时时间未被消费;
3、队列如何绑定死信交换机:
给队列设置参数: x-dead-letter-exchange :死信交换机的名称 x-dead-letter-routing-key:死信交换机的routing-key RepublishMessageRecoverer策略:死信交换机:可以像Republish一样做一些消息兜底的处理,还可以做一些超市消息的处理。
二、TTL:
1、什么是TTL:
TTL 全称 Time To Live(存活时间/过期时间)。 当消息到达存活时间后,还没有被消费,消息会成为死信。 RabbitMQ可以对消息设置过期时间,也可以对整个队列(Queue)设置过期时间。
2、设置:
?设置队列过期时间使用参数:x-message-ttl,单位:ms(毫秒),会对整个队列消息统一过期。
? 设置消息过期时间使用参数:expiration。单位:ms(毫秒),当该消息在队列头部时(消费时),会单独判断这一消息是否过期。
? 如果两者都进行了设置,以时间短的为准。
3、实现:
我们声明一组死信交换机和队列,基于注解方式: 要给队列设置超时时间,需要在声明队列时配置x-message-ttl属性:
发送消息时,给消息本身设置超时时间:
三、延迟队列:
1、什么是延迟队列:
延迟队列,即消息进入队列后不会立即被消费,只有到达指定时间后,才会被消费。
2、案例分析:
下单后,30分钟未支付,取消订单,回滚库存
实现如上的案例,用户下单后会在数据库表中添加一条下单的记录。我们创建一个定时任务,比如每隔1分钟就查询这些订单记录,判断这些记录的下单时间和当前的时间相差是否超过30分钟,如果超过,则判断订单的状态,进而决定是否取消订单,回滚库存。
但是上面这种解决方式不够优雅,因为这样解决肯定会存在1分钟的误差,而且总是要查询。
如果使用延迟队列,用户下单后向消息队列发送一条消息,这条消息在30分钟后再被库存系统消费,库存系统消费了这条消息后再去判断订单的状态。这样只有在判断订单状态的时候会去查询一次数据库,不用循环去查询,性能更好。
3、延迟队列的实现:
RabbitMQ中没有延迟队列的实现,但我们可以使用TTL和死信队列来实现延迟队列。 只需要给正常的队列设置过期时间为30分钟,然后把这个队列绑定到死信交换机,不去消费这些消息,而是让这些消息主动成为死信进而进入死信队列;然后让库存系统去监听死信队列。这样就可以让订单系统发送一条消息,库存系统30分钟后才收到这条消息。
4、使用插件实现延迟队列:
DelayExchange的本质还是官方的三种交换机,只是添加了延迟功能。因此使用时只需要声明一个交换机,交换机的类型可以是任意类型,然后设定delayed属性为true即可。 基于java代码的方式: 然后我们向这个delay为true的交换机中发送消息,一定要给消息添加一个header:x-delay,值为延迟的时间,单位为毫秒:
|