消息队列(Message Queue,简称MQ),指保存消息的一个容器,本质是个队列。
消息队列中间件是分布式系统中重要的组件(单机版也可用:单机版指的是在服务器上安装),主要解决应用耦合,异步消息,流量削锋等问题。实现高性能,高可用,可伸缩和最终一致性架构。
使用较多的消息队列有ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ。
名词解释
- 把数据放到(push)消息队列叫做生产者
- 从消息队列里边取(get)数据叫做消费者
在异步处理,应用解耦,流量销峰时使用。
2.1 异步处理有些业务不想也不需要立即处理消息。消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多少,然后在需要的时候再去处理它们。
下图中下订单过程,传统的做法有两种:1.串行的方式;2.并行的方式,而引入消息队列,将不是必须的业务逻辑,异步处理。
- 串行方式是依次支付,赠送积分,短信通知,以上三个任务全部完成后,才结束,耗时150ms。
- 并行是在支付后让赠送积分和短信通知异步进行,耗时100ms
- 引入消息队列,将不是必须的业务逻辑,异步处理,耗时50ms
因此在引入MQ后,系统的吞吐量提高了。
2.2 应用解耦用户下单支付后,支付系统需要通知短信服务和积分服务。传统的做法是,支付系统调用短信系统和积分系统的接口。
传统模式的缺点:
- 假如短信系统或积分系统出现故障,则支付系统将失败从而导致整个流程失败。
- 支付系统和短信积分系统耦合度过高。
如何解决以上问题呢?引入应用消息队列后的方案
订单系统与库存系统耦合
如何解决以上问题呢?引入应用消息队列后的方案,如下图:
支付系统:用户支付,支付系统完成持久化处理,将消息写入消息队列,返回用户支付下单成功
积分系统:订阅支付的消息,采用拉/推的方式,获取支付信息,积分系统根据支付信息,进行积分 *** 作
短信系统:订阅支付的消息,采用拉/推的方式,获取支付信息,短信系统根据支付信息,进行短信 *** 作
假如:在下单时积分系统或短信系统不能正常使用。也不影响正常支付,因为支付后,支付系统写入消息队列就不再关心其他的后续 *** 作了。实现支付系统与积分系统,支付系统和短信系统的应用解耦。
2.3 流量削峰假如双十一当天,很多用户同时下订单,流量激增,订单系统可能会扛不住这么大的请求而挂断。为解决这个问题,一般需要在应用前加入消息队列。
有了消息队列可以将大量请求缓存起来,分散到很长一段时间处理,这样可以大大提到系统的稳定性和用户体验。
例如图中本来8k/s的请求,经过MQ缓存后
业务系统正常时段的QPS如果是1000,流量最高峰是10000,为了应对流量高峰配置高性能的服务器显然不划算,这时可以使用消息队列对峰值流量削峰
再比如领导要给一万名员工下发邮件通知,这显然是瞬时高并发的。这个时候就可以在消息队列缓存一部分
如图:气象局不需要写很多对外调用的接口,只需要为网易,新浪,百度等开通消息队列访问权限,网易,新浪等直接订阅气象局的消息,获取最新天气预报数据。如果新的网站想要加入,气象局也不需要做任何代码变更。
重复消费问题可以说是mq中普遍存在的问题,不管你用哪种mq都无法避免。
如果重复消息不做正确的处理,会对业务造成很大的影响,产生重复的数据,或者导致数据异常,比如会员系统多开通了一个月的会员。
有哪些场景会出现重复的消息呢?
- 消息生产者产生了重复的消息
- kafka和rocketmq的offset被回调了
- 消息消费者确认失败
- 消息消费者确认时超时了
- 业务系统主动发起重试
如果mq的消费者业务处理异常的话,就会出现数据一致性问题。
比如:一个完整的业务流程是,下单成功之后,送100个积分。下单写库了,但是消息消费者在送积分的时候失败了,就会造成数据不一致的情况,即该业务流程的部分数据写库了,另外一部分没有写库。
如果下单和送积分在同一个事务中,要么同时成功,要么同时失败,是不会出现数据一致性问题的。但由于跨系统调用,为了性能考虑,一般不会使用强一致性的方案,而改成达成最终一致性即可。
3.3 系统复杂度提升这里说的系统复杂度和系统耦合性是不一样的,比如以前只有:系统A、系统B和系统C 这三个系统,现在引入mq
之后,你除了需要关注前面三个系统之外,还需要关注mq服务,需要关注的点越多,系统的复杂度越高。
mq的机制需要:生产者、mq服务器、消费者。
有一定的学习成本,需要额外部署mq服务器,而且有些mq比如:rocketmq,功能非常强大,用法有点复杂,如果使用不好,会出现很多问题。有些问题,不像接口调用那么容易排查,从而导致系统的复杂度提升了。
4 常见的MQ产品 4.1 RabbitMQRabbitMQ 于 2007 年发布,是使用 Erlang 编程语言编写的,开箱即用的额消息队列,RabbitMQ 是一个相当轻量级的消息队列,非常容易部署和使用。
RabbitMQ 的几个问题:
- RabbitMQ 对消息堆积的支持并不好,当大量消息积压的时候,会导致 RabbitMQ 的性能急剧下降。
- RabbitMQ 的性能是这几个消息队列中最差的,大概每秒钟可以处理几万到十几万条消息。如果应用对消息队列的性能要求非常高,那不要选择 RabbitMQ。
- RabbitMQ 使用的编程语言 Erlang,扩展和二次开发成本高。
RocketMQ 是阿里在 2012 年开源的消息队列产品,用 Java 语言实现,在设计时参考了 Kafka,并做出了自己的一些改进,后来捐赠给 Apache 软件基金会,2017 正式毕业,成为 Apache 的顶级项目。RocketMQ 在阿里经历过多次双十一考验,它的性能、稳定性和可靠性都是值得信赖的。
RocketMQ 的性能比 RabbitMQ 要高一个数量级,每秒钟大概能处理几十万条消息。
4.3 KafkaApache Kafka 是一个分布式消息发布订阅系统。Kafka 与周边生态系统的兼容性是最好的没有之一,尤其在大数据和流计算领域,几乎所有的相关开源软件系统都会优先支持 Kafka。Kafka 使用 Scala 和 Java 语言开发
- 中小型公司,技术实力较为一般,技术挑战不是特别高,用 RabbitMQ 是不错的选择;
- 大型公司,基础架构研发实力较强,用 RocketMQ 是很好的选择。
- 如果是大数据领域的实时计算、日志采集等场景,用 Kafka 是业内标准的,绝对没问题,社区活跃度很高,绝对不会黄,何况几乎是全世界这个领域的事实性规范。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)