消息队列是干什么的?
在实际应用中,消息队列大致有五个功能:
- 异步处理
- 应用解耦
- 流量削峰/限流
- 日志处理
- 消息通讯
1.异步处理
场景说明,用户注册后,需要发注册邮件和注册短信。传统的做法有两种:
- 串行的方式
- 并行的方式
a、串行方式:将注册信息写入数据库成功后,发送注册邮件,再发送注册短信。以上三个任务全部完成后,返回给客户端。
b、并行方式:将注册信息写入数据库成功后,发送注册邮件的同时,发送注册短信。以上三个任务完成后,返回给客户端。与串行的差别是,并行的方式可以提高处理的时间。
假设三个业务节点每个使用50毫秒钟,不考虑网络等其他开销,则串行方式的时间是150毫秒,并行的时间可能是100毫秒。
但100毫秒还是太慢了,这样传统的方式会使系统的性能(并发量,吞吐量,响应时间)会有瓶颈。如何解决这个问题呢?引入消息队列。
引入消息队列,将不是必须的业务逻辑,异步处理。改造后的架构如下:
2.应用解耦
场景说明:用户下单后,订单系统需要通知库存系统。传统的做法是,订单系统调用库存系统的接口。
传统模式的缺点:假如库存系统无法访问,则订单减库存将失败,从而导致订单失败,订单系统与库存系统耦合
如何解决以上问题呢?引入应用消息队列后的方案,如下图:
订单系统:用户下单后,订单系统完成持久化处理,将消息写入消息队列,返回用户订单下单成功。
库存系统:订阅下单的消息,采用拉/推的方式,获取下单信息,库存系统根据下单信息,进行库存操作。
假如:在下单时库存系统不能正常使用。也不影响正常下单,因为下单后,订单系统写入消息队列就不再关心其他的后续操作了。实现订单系统与库存系统的应用解耦。
3.流量削峰
流量削锋也是消息队列中的常用场景,一般在秒杀或团抢活动中使用广泛。
应用场景:秒杀活动,一般会因为流量过大,导致流量暴增,应用挂掉。为解决这个问题,一般需要在应用前端加入消息队列,这样:
- 可以控制活动的人数
- 可以缓解短时间内高流量压垮应用
用户的请求,服务器接收后,首先写入消息队列。假如消息队列长度超过最大数量,则直接抛弃用户请求或跳转到错误页面。
秒杀业务根据消息队列中的请求信息,再做后续处理。
4.日志处理
日志处理是指将消息队列用在日志处理中,比如Kafka的应用,解决大量日志传输的问题。架构简化如下:
日志采集客户端,负责日志数据采集,定时写受写入Kafka队列。
Kafka消息队列,负责日志数据的接收,存储和转发。
日志处理应用:订阅并消费kafka队列中的日志数据 。
5.消息通讯
消息通讯是指,消息队列一般都内置了高效的通信机制,因此也可以用在纯的消息通讯。比如实现点对点消息队列,或者聊天室等。
点对点通讯:
客户端A和客户端B使用同一队列,进行消息通讯。
聊天室通讯:
客户端A,客户端B,客户端N订阅同一主题,进行消息发布和接收。实现类似聊天室效果。
消息队列应用示例
1.电商系统
其中会员系统、订单系统为写入消息的主要系统,短信系统、配送系统为收到消息并进行处理的扩展系统。
消息队列采用高可用,可持久化的消息中间件。比如Active MQ,Rabbit MQ,Rocket Mq。
- 应用将主干逻辑处理完成后,写入消息队列。消息发送是否成功可以开启消息的确认模式。(消息队列返回消息接收成功状态后,应用再返回,这样保障消息的完整性)
- 扩展流程(发短信,配送处理)订阅队列消息。采用推或拉的方式获取消息并处理。
- 消息将应用解耦的同时,带来了数据一致性问题,可以采用最终一致性方式解决。比如主数据写入数据库,扩展应用根据消息队列,并结合数据库方式实现基于消息队列的后续处理。
2.日志系统
分为Zookeeper注册中心,日志收集客户端,Kafka集群和Storm集群(OtherApp)四部分组成。
- Zookeeper注册中心,提出负载均衡和地址查找服务
- 日志收集客户端,用于采集应用系统的日志,并将数据推送到kafka队列
- Kafka集群:接收,路由,存储,转发等消息处理
- Storm集群:与OtherApp处于同一级别,采用拉的方式消费队列中的数据
消息队列大致什么样子
消息队列,一般我们会简称它为MQ(Message Queue)。
先不管消息(Message)这个词,来看看队列(Queue)。队列是一种先进先出的数据结构。
消息队列可以简单理解为:把要传输的数据放在队列中。其中:
- 把数据放到消息队列叫做生产者
- 从消息队列里边取数据叫做消费者
为什么要用中间件
Java中是提供了许多队列的,为什么要单独做一个消息队列的中间件?
原因如下:
- 高可用:如果是单机的消息队列,万一这台机器挂了,那我们整个系统几乎就是不可用了。所以需要一个消息队列的分布式集群中。
- 数据丢失问题:我们将数据写到消息队列上,系统B和C还没来得及取消息队列的数据,就挂掉了。如果没有做任何的措施,我们的数据就丢了。所以需要像Redis、Zookeeper一样有持久化的方式。
消息队列模型及组成
消息队列模型:
- 点对点模式
- 发布/订阅模式
点对点模式:是一个基于拉取或轮询的消息传送模型,由消费者主动拉取数据,客户端需要实时开启一个线程监控队列中是否有数据。
发布/订阅模式:是一个基于推送的消息传送模型,由MQ主动推送消息给所有订阅者,即使当前订阅者不可用。
消息队列组成:
- Broker:消息服务器,作为server提供消息核心服务
- Producer:消息生产者,业务的发起方,负责生产消息传输给broker
- Consumer:消息消费者,业务的处理方,负责从broker获取消息并进行业务逻辑处理
- Topic:主题,发布订阅模式下的消息统一汇集地,不同生产者向topic发送消息,由MQ服务器分发到不同的订阅者,实现消息的广播
- Queue:队列,PTP模式下,特定生产者向特定queue发送消息,消费者订阅特定的queue完成指定消息的接收
- Message:消息体,根据不同通信协议定义的固定格式进行编码的数据包,来封装业务数据,实现消息的传输
https://blog.csdn.net/yunzhaji3762/article/details/79763660
常见的消息队列中间件
- Active MQ
- Rabbit MQ
- Rocket MQ
- kafka
- Redis
- ZeroMQ
Active MQ
性能:万级的吞吐量,主从架构实现高可用,丢失消息的可能性非常低
优点:社区活跃
缺点:性能比较差,社区活跃,但版本更新慢(不推荐)
Rabbit MQ
性能:万级的吞吐量,主从架构实现高可用,丢失消息的可能性非常低
优点:基于 erlang 开发,所以并发能力很强,性能极其好,延时很低,达到微秒级。
缺点:因为 RabbitMQ 基于 erlang 开发,所以国内很少有公司有实力做erlang源码级别的研究和定制。
应用:如果业务场景对并发量要求不是太高(十万级、百万级),那这四种消息队列中,RabbitMQ 一定是你的首选。
Rocket MQ
性能:十万级甚至是百万级的吞吐量,分布式实现高可用,消息理论上不会丢失。
优点:阿里出品,Java 系开源项目,源代码我们可以直接阅读,然后可以定制自己公司的MQ,并且 RocketMQ 有阿里巴巴的实际业务场景的实战考验。
缺点:社区活跃度一般,可能会黄,接口这块不是按照标准 JMS 规范走的有些系统要迁移需要修改大量代码。
应用:如果公司有技术实力,用RocketMQ 挺好的。
kafka
性能:十万级甚至是百万级的吞吐量,分布式实现高可用,消息理论上不会丢失。
优点:提供超高的吞吐量,ms 级的延迟,极高的可用性以及可靠性,而且分布式可以任意扩展。社区活跃度很高,绝对不会黄。
缺点:功能较为简单,仅仅提供较少的核心功能,可能消息重复消费,对数据准确性会造成极其轻微的影响。这点轻微影响可以忽略这个特性天然适合大数据实时计算以及日志收集。
应用:如果是大数据领域的实时计算、日志采集等场景,用 Kafka 是业内标准的,绝对没问题,,何况几乎是全世界这个领域的事实性规范。
- 消息重复消费了怎么办?
- 保证消息是绝对有顺序的怎么做?
转自:https://www.cnblogs.com/ExMan/p/10261095.html