延迟队列(二)基于rabbitmq的ttl实现

rabbitmq本身没有延迟队列,自定义延迟时间,但是,rabbitmq的ttl机制,可以设置消息的过期时间。并且,可以设置,消息过期之后,转入哪一个队列。
也就是主要两个机制:

  1. ttl:消息自定义过期时间。
  2. dxl:消息过期之后转入exchange

参考:详细介绍Spring Boot + RabbitMQ实现延迟队列

大概流程:
1、发送一个任务,这个任务就是一个消息,任务到期时间就是消息的ttl过期时间。
2、这个ttl过期之后,会转入指定的exchange,指定的routing key,路由到指定的queue。
3、这个queue有消费者订阅,这个消费者,执行到期任务的,或者把到期任务转发出去别人执行。

可以看到,相对前面说的基于redis的zset,这个方式,极其简单。
我们对比一下:

1、rabbitmq比redis的zset,要优雅,简单。

2、rabbitmq不需要轮询,直接一个标准的mq消费者,就能收到延迟消息的推送。

3、假设同时到期的任务太多,可以把消息放入线程池处理,处理完才应答,不过要保证幂等性。

4、在性能方面:依赖于rabbitmq本身的性能,自然不低。更大的压力,应该来自于大量任务同时到期之后的处理,也就是消费者的处理,可以多个消费者,分担压力。

5、扩容方面:rabbitmq本身压力不大,存储容量,如果单纯存储消息的话,容量也不是问题。

6、高可用方面:rabbitmq本身的镜像集群可以做到高可用。

7、消息重试:消费者没有收到消息,rabbitmq自带重试机制,可以配置重试间隔,重试次数。消费者如果收到消息但是处理失败,则可以重新设置过期时间,重新放入队列,或者,放入其他地方,人工找到失败问题,处理。

8、消息可达性方面:rabbitmq的应答机制,能够保证消息必达。

优点:如果架构已经引入了rabbitmq,很容易实现。
缺点:无法取消删除已经入队的任务,某些业务可能不适合。

之前的zset:
1、基于http轮询:麻烦,如果用http夯住,可以实现,稍微麻烦一点。

2、假设同期到期任务太多:客户端消费者,一个http请求,拉取很多任务,然后一个一个处理。服务端,把这些消息重新设置到期时间,放入队列,等待客户端执行完,发送删除请求,否则一直重试。

3、性能方面:服务端本身,轮询线程不多,性能不是问题。更大的压力,来自于,客户端的http连接拉取任务,要扩展这方面,可以跑多个服务端。

4、扩容方面:消息存储容量依赖于redis,不是问题。服务端的轮询性能压力也不大。

6、高可用方面:依赖于redis的高可用。

7、消息重试:消费者没有消息,会再发http请求,没有问题。 消费者如果消息处理失败,则一样可以自定义重试机制。

8、消息可达性方面:只有客户端发送了删除命令,否则消息不会丢。

最大的问题:麻烦,需要做一个这样的延迟队列服务。

总结:1、rabbitmq,简单,好用。但是不能删除消息。2、zset,需要轮询,比较麻烦,如果把zset嵌入到其他服务,则耦合性大,没有rabbitmq优雅。

你可能感兴趣的:(延迟队列(二)基于rabbitmq的ttl实现)