本文将介绍大名鼎鼎的消息队列(MQ)的原理,应用场景和常见问题。
日常开发中,可能会经常遇到这几类问题:
- 系统中批量更新(增,删,改)功能接口,如果业务比较复杂,加之数据量庞大,这类同步操作是很耗时的,这时候需要进行异步处理。
- 电子商务网站在促销活动时,会在短时间内高并发,需要削平高峰期的并发事务。
- 为了提高系统的可扩展性,希望各个模块之间不存在直接调用,开发低耦合的系统,对各个模块之间进行解耦。
以上场景,都可以使用消息队列有效解决。
什么是消息队列?
消息(Message)是指在应用间传送的数据(比如字符串,json等),消息队列(Message Queue,简称MQ)是一个古老的计算机术语,UNIX进程间通信就用到了消息队列技术:一个进程把数据写入某个特定队列中,其它队列读取特定队列中的数据实现异步通信。而现在我们所说的MQ通常指的是独立的消息队列中间件,利用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通信来进行分布式系统的集成。
传递模式
消息队列一般有两种传递模式:
- 点对点(Point to Point,简称PTP):消息生产者发送消息到队列,消费者从队列中接收消息。消息被消费以后,queue中不再存储,queue支持存在多个消费者,但是一个消息只能被一个消费者消费。
- 发布 / 订阅(Pub / Sub):发布订阅(一对多)广播形式,消息发布者将消息发布到某个主题(Topic),消息订阅者从主题中订阅消息(得到消息的拷贝),一个消息可以同时被多个消费者订阅,并会被所有订阅者消费。
组成
- Broker: 消息服务器,作为server提供消息核心服务
- Producer:消息生产者,业务的发起方,生产消息传输给broker
- Consumer:消息消费者,业务处理方,负责从broker获取消息并进行业务逻辑处理
- Topic:主题,Pub/sub模式下 消息统一汇聚地,不同生产者向topic发送消息,由MQ服务器分发到不同订阅者,实现消息的广播。
- Queue:队列,PTP模式下,特定生产者向特定队列发送消息,消费者订阅特定的queue完成指定消息的接收与消费。
- Message:消息体,根据不同通信协议定义的固定格式编码数据包,来封装业务数据,实现消息的传输。
消息队列的作用
介绍几个消息队列的重要作用:
- 解耦:传统的软件开发模式,各个模块之间相互调用,数据共享,每个模块都要时刻关注其他模块的是否更改或者是否挂掉等等,使用消息队列,可以避免模块之间直接调用,将所需共享的数据放在消息队列中,对于新增业务模块,只要对该类消息感兴趣,即可订阅该类消息,对原有系统和业务没有任何影响,降低了系统各个模块的耦合度,提高了系统的可扩展性。
- 异步:消息队列提供了异步处理机制,在很多时候应用不想也不需要立即处理消息,允许应用把一些消息放入消息中间件中,并不立即处理它,在之后需要的时候再慢慢处理。
- 削峰:在访问了骤增的场景下,需要保证应用系统的平稳性,但是这样突发流量并不常见,如果以这类峰值的标准而投放资源的话,那无疑是巨大的浪费,使用消息队列能够使关键组件支撑突发访问压力,不会因为突发的超负荷请求而完全崩溃。消息队列的容量可以配置的很大,如果采用磁盘存储消息,则几乎等于“无限”容量,这样一来,高峰期的消息可以被积压起来,在随后的时间内进行平滑的处理完成,而不至于让系统短时间内无法承载而导致崩溃,在电商网站的秒杀抢购这种突发性流量很强的业务场景中,消息队列的强大缓冲能力可以很好的起到削峰作用。
消息队列技术选型
现在有很多主流的消息中间件,包括:ActiveMQ, RabbitMQ,Kafka, RocketMQ,Redis。选型时要结合具体的应用场景和自身的业务需求,从功能、性能、运维、可靠性+可用性等维度进行多重考量。
ActiveMQ
Apache出品,Java开发,目前所占的市场份额不多。
RabbitMQ
Erlang语言实现AMQP协议的消息中间件,并发能力很强,性能及其好,延时很低(达到微妙级),特点:可靠性,可用性,扩展性,功能丰富。
Kafka
LinkedIn使用Scala开发的分布式,多分区,多副本且基于zookeeper协调的分布式消息系统,提供了超高的吞吐量,毫秒级延迟,极高的可用性和可靠性。
RocketMQ
阿里出品,Java开发,高吞吐,高可用,适合大规模分布式应用,经过多次双十一的洗礼,实力不容小觑。
所谓的**消息中间件大道至简:一发一存一消费,没有最好的消息中间件,只有最合适的消息中间件。 **
带来的问题
引入消息队列后,我们需要考虑哪些问题呢?
1. 消息堆积
这是一个很常见的问题,如果消息消费的时间太久,或者服务器故障,导致消息堆积。
2. 消息丢失
消息堆积一个处理方案就是给消息加上超时时间判定,这样就会衍生一个问题,当消息堆积,处理完成之后,就会存在一定消息的丢失,或者服务器宕机也会导致消息丢失,需要针对此类问题做好应对方案。
3. 消息准确消费
保证消息被准确消费,且不存在重复消费的问题。
推荐大家的项目开发中使用消息队列,并不是“杀鸡焉用牛刀”的问题,而是未雨绸缪,随着项目不断发展,你终将从消息队列中获益。
以上。
最后,祝大家新年快乐!