logo头像
Snippet 博客主题

ActiveMq的Topic消息模式,订阅者宕机重启,消息丢失的解决方案

本文于 825 天之前发表,文中内容可能已经过时。

消息队列中间件ActiveMq,我熟知的应用场景有,异步处理,削峰平谷和应用解耦,可扩展性,还有一个不经常想到的,解决并发问题。

异步处理

比如订单系统,订单创建的流程很长,有订单号的生成,优惠券的使用,配送流程,库存的扣减,通知邮件与短信,如果传统的做法,串行化处理这些流程,那么这一次的请求链路消耗的时间特别长,影响客户体验,占用线程资源过长时间,吞吐量自然上不去,比如可以将邮件,短信作为消息发给MQ,让邮件,短信平台来消费,异步处理,提高了系统的响应速度。

削峰平谷

在做促销抢购活动期间,高并发的订单请求,数据库的瓶颈就出现了,大量的读写操作,瞬间压爆数据库,我们可以借助MQ来给高并发请求做个缓冲,某些场景下可以设置队列长度,如果超过队列的容量直接拒绝用户请求,比如小米官网的手机抢购。

应用解耦

分布式系统中,系统之间通信相互依赖,耦合度高,如果某个接口服务宕机了,就会影响依赖方。比如下单接口之间调用库存系统的话,库存系统宕机的话,下单接口就直接失败了,但是如果下单请求推给MQ,由库存系统消费,如果库存系统宕机了,也不会影响下单。

可扩展性

电商系统,下单订单,会有通知用户下单结果,方式有邮件,短信,如果后续需要有下单送优惠券的功能,然后我们的消息模式是TOPIC模式,就可以新增具有送优惠券功能的订阅者即可,新的功能不需要修改订单系统的代码,符合软件设计的开闭原则,扩展性也非常强。

解决并发问题

有这样一个场景,比如这个模块有个定时任务扫描符合条件的会员,然后给会员发积分,如果是部署多台实例,那么会有多个定时任务在送积分,会出现重复捞取到满足条件的会员记录,导致了重复送积分,而MQ的点对点的消息模式,保证只有一个消费者消费同一个消息,只需要安排一台master实例去捞取数据,再发给MQ,让订阅者去消费送积分,很巧妙的解决了并发的问题。

ActiveMQ的使用,带来的一些问题

上面聊了一下,ActiveMQ的应用,同时也带来了一些问题。

1:生产者发送消息给MQ服务器,MQ服务器接收到消息后,MQ宕机消息会不会丢失?

2:TOPIC的消息模式下,MQ接收到消息,这时候订阅者宕机了或者重启了,那消息会丢失,有什么解决方案?

第一个问题,ActiveMq支持消息的持久化,所以MQ服务器宕机了,重启后消息也不会丢失。
第二个问题网上也有如下解释:

Pub/Sub的特点

每个消息可以有多个消费者
发布者和订阅者之间有时间上的依赖性。针对某个主题(Topic)的订阅者> ,它必须创建一个订阅者之后,才能消费发布者的消息
为了消费消息,订阅者必须保持运行的状态

为了缓和这样严格的时间相关性,JMS允许订阅者创建一个可持久化的订阅> 。这样,即使订阅者没有被激活(运行),它也能接收到发布者的消息。

解释起来就是,关于发布-订阅的消息模式,即TOPIC,生产者跟消费者之间的时间严格依赖性,JMS提供了解决方案,订阅模式分持久订阅者与非持久订阅者,这样声明成持久订阅者即使宕机了,消息在broker也就是MQ服务器的磁盘里面不会丢失,订阅者重启后仍然可以消费消息。