消息队列已经逐渐成为企业IT系统内部通讯的核心手段。它具备低耦合、可靠投递、广播、流量控制、最终一致性等一系列功能,成为异步RPC的主要手段之一。前端
消息被处理的过程至关于流程A被处理。咱们这里以一个实际的模型来讨论下,好比用户下单成功时给用户发短信,若是没有这个消息队列,咱们会选择同步调用发短信的接口,数据库
并等待短息发送成功,这时候假设短信接口实现出现问题了,或者短信调用端超时了,又或者短信发送达到上限了,咱们是选择重试几回仍是放弃,仍是选择把这个放到数据库缓存
过一段时间再看看呢,无论怎样,实现都很复杂。服务器
咱们能够将发短信这个请求放在消息队列里,消息队列按照必定的顺序挨个处理队列里的消息,当处理到发送短信的任务时,通知短信服务发送消息,若是出现以前出现的问题,那么把这个消息从新放到消息队列中。网络
消息队列的好处:并发
1.成功完成了一个异步解耦的过程。短信发送时只要保证放到消息队列中就能够了,接着作后面的事情就行。一个事务只关心本质的流程,须要依赖其余事情可是不那么重要的时候,有通知便可,无需等待结果。每一个成员没必要受其余成员影响,能够更独立自主,只经过一个简单的容器来联系。负载均衡
对于咱们的订单系统,订单最终支付成功以后可能须要给用户发送短信积分什么的,但其实这已经不是咱们系统的核心流程了。若是外部系统速度偏慢(好比短信网关速度很差),那么主流程的时间会加长不少,用户确定不但愿点击支付过好几分钟才看到结果。那么咱们只须要通知短信系统“咱们支付成功了”,不必定非要等待它处理完成。异步
2.保证了最终一致性,经过在队列中存听任务保证它最终必定会执行。分布式
最终一致性指的是两个系统的状态保持一致,要么都成功,要么都失败。固然有个时间限制,理论上越快越好,但实际上在各类异常的状况下,可能会有必定延迟达到最终一致状态,但最后两个系统的状态是同样的。
业界有一些为“最终一致性”而生的消息队列,如Notify(阿里)、QMQ(去哪儿)等,其设计初衷,就是为了交易系统中的高可靠通知。
以一个银行的转帐过程来理解最终一致性,转帐的需求很简单,若是A系统扣钱成功,则B系统加钱必定成功。反之则一块儿回滚,像什么都没发生同样。
然而,这个过程当中存在不少可能的意外:高并发
可见,想把这件看似简单的事真正作成,真的不那么容易。全部跨VM的一致性问题,从技术的角度讲通用的解决方案是:
消息队列的基本功能之一是进行广播。若是没有消息队列,每当一个新的业务方接入,咱们都要联调一次新接口。有了消息队列,咱们只须要关心消息是否送达了队列,至于谁但愿订阅,是下游的事情,无疑极大地减小了开发和联调的工做量。
3.提速。假设咱们还须要发送邮件,有了消息队列就不须要同步等待,咱们能够直接并行处理,而下单核心任务能够更快完成。加强业务系统的异步处理能力。甚至几乎不可能出现并发现象。
4.削峰和流控。不对于不须要实时处理的请求来讲,当并发量特别大的时候,能够先在消息队列中做缓存,而后陆续发送给对应的服务去处理
试想上下游对于事情的处理能力是不一样的。好比,Web前端每秒承受上千万的请求,并非什么神奇的事情,只须要加多一点机器,再搭建一些LVS负载均衡设备和Nginx等便可。但数据库的处理能力却十分有限,即便使用SSD加分库分表,单机的处理能力仍然在万级。因为成本的考虑,咱们不能奢求数据库的机器数量追上前端。
这种问题一样存在于系统和系统之间,如短信系统可能因为短板效应,速度卡在网关上(每秒几百次请求),跟前端的并发量不是一个数量级。但用户晚上个半分钟左右收到短信,通常是不会有太大问题的。若是没有消息队列,两个系统之间经过协商、滑动窗口等复杂的方案也不是说不能实现。但系统复杂性指数级增加,势必在上游或者下游作存储,而且要处理定时、拥塞等一系列问题。并且每当有处理能力有差距的时候,都须要单独开发一套逻辑来维护这套逻辑。因此,利用中间系统转储两个系统的通讯内容,并在下游系统有能力处理这些消息的时候,再处理这些消息,是一套相对较通用的方式。
总而言之,消息队列不是万能的。对于须要强事务保证并且延迟敏感的,RPC是优于消息队列的。
对于一些无关痛痒,或者对于别人很是重要可是对于本身不是那么关心的事情,能够利用消息队列去作。
支持最终一致性的消息队列,可以用来处理延迟不那么敏感的“分布式事务”场景,并且相对于笨重的分布式事务,多是更优的处理方式。
当上下游系统处理能力存在差距的时候,利用消息队列作一个通用的“漏斗”。在下游有能力处理的时候,再进行分发。
若是下游有不少系统关心你的系统发出的通知的时候,果断地使用消息队列吧。
消息队列的使用场景:
主要特色是异步处理,主要目的是减小请求响应时间和解耦。因此主要的使用场景就是将比较耗时并且不须要即时(同步)返回结果的操做做为消息放入消息队列。
可是对于用户来讲,注册功能实际只须要第一步,只要服务端将他的帐户信息存到数据库中他即可以登陆上去作他想作的事情了。至于其余的事情,非要在这一次请求中所有完成么?值得用户浪费时间等你处理这些对他来讲可有可无的事情么?因此实际当第一步作完后,服务端就能够把其余的操做放入对应的消息队列中而后立刻返回用户结果,由消息队列异步的进行这些操做。
或者还有一种状况,同时有大量用户注册你的软件,再高并发状况下注册请求开始出现一些问题,例如邮件接口承受不住,或是分析信息时的大量计算使cpu满载,这将会出现虽然用户数据记录很快的添加到数据库中了,可是却卡在发邮件或分析信息时的状况,致使请求的响应时间大幅增加,甚至出现超时,这就有点不划算了。面对这种状况通常也是将这些操做放入消息队列(生产者消费者模型),消息队列慢慢的进行处理,同时能够很快的完成注册请求,不会影响用户使用其余功能。
为何须要消息队列?
生产和消费的速度或者稳定性不一致。
当今市面上有不少主流的消息中间件,如老牌的ActiveMQ、RabbitMQ,煊赫一时的Kafka,阿里巴巴自主开发的Notify、MetaQ、RocketMQ等。
Kafka是一种高吞吐量的分布式发布订阅消息系统,它能够处理消费者规模的网站中的全部动做流数据。
Kafka 有以下特性: