消息队列基础 | 青训营笔记

113 阅读6分钟

这是我参与「第五届青训营」伴学笔记创作活动的第10天

为什么要使用消息队列? 消息队列使用场景:异步、解耦、调峰

异步:比如审批场景,需要一个流程完成多个步骤。 比如通过/拒绝后,需要发送消息通知,代理,通知下游系统。 如果这些步骤同步执行,整个调用链太长,耗时太长,影响整体性能。 因此消息通知、代理、通知下游的步骤可以异步处理。

解耦:如果使用多线程进行异步,会造成与下游系统的耦合。 每次连接一个系统,都会添加一个接口调用,然后重新发布系统。 使用消息队列将消息发布到消息队列,下游系统直接监听审批流程消息,感知审批进度,达到解耦的目的。

调峰:主要是应对突发流量冲击系统,导致系统过载。 消息队列可以控制消费速度,根据系统的处理能力进行消费,比如秒杀系统。

使用消息队列引起的一些问题 增加系统复杂度:引入一个中间件必然会增加系统的复杂度,还要考虑消息的重复消费、消息丢失、消息的顺序消费等。 数据一致性:数据一致性是分布式系统固有的问题,在消息队列中也是如此。 在审批过程中,如何保证消息、代理、下游系统的处理都成功? 如何保证数据一致性呢? 通过分布式事务可以保证数据的一致性。 降低可用性:当引入中间件时,必然会出现中间件故障,因此也需要保证中间件的可用性。 JMS 与 AMQP JMS:JAVA Message Service,java消息服务

jms是java消息服务的缩写,jms客户端可以使用jms服务进行异步消息传输。 ActiveMQ是基于JMS规范实现的。

jms 支持两种消息模型:

点对点 (P2P) 模型 发布/订阅(Pub/Sub)模型 JMS 五种不同的消息体格式:

StreamMessage -- Java 原始值流 MapMessage -- 一组名称-值对 TextMessage - 字符串对象 ObjectMessage - 序列化的 Java 对象 BytesMessage--字节流

AMQP: Advanced Message Queuing Protocol,高级消息队列协议

对比:

JMSAMQP
定义java API协议
跨语言
跨平台
支持的消息类型P2P、Pub/Sub提供了五种消息模型:①direct exchange;②fanout exchange;③topic change;④headers exchange;⑤system exchange。本质来讲,后四种和 JMS 的 pub/sub 模型没有太大差别,仅是在路由机制上做了更详细的划分
支持消息类型支持多种消息类型 ,我们在上面提到过byte[](二进制)

常见消息队列对比:

特性ActiveMQRabbitMQRocketMQKafka
单机吞吐量万级万级10万级10万级
topic数量对吞吐量的影响topic可以达到几百/几千级别,吞吐量小幅下降topic从几十到几百,吞吐量会大幅下降
时效性ms级微妙级ms级ms级以内
可用性高,基于主从架构高,基于主从架构非常高,分布式架构非常高,分布式架构
消息可靠性有较低概率丢失数据基本不丢经过参数优化配置,可以做到不丢失经过参数优化配置,可以做到不丢失
功能支持MQ领域的功能及其完备基于erlang开发,并发能力很强,性能极好,延时很低MQ功能较完善,分布式,扩展性好功能较简单,主要支持简单的MQ功能,在大数据领域的实时计算及日志采集被大规模使用
社区活跃度

消息队列选型:

  • ActiveMQ 和 RabbitMQ 相对于 RocketMQ 和 Kafka 吞吐量低一个数量级别,ActiveMQ 和 RabbitMQ 单机支持万级吞吐量,而 RocketMQ 和 Kafka 单机支持10万级吞吐量。
  • RocketMQ topic 数量可以达到几百/几千级别,吞吐量小幅下降,Kafka 的 topic 数量从几十到几百,吞吐量会大幅下降
  • RabbitMQ 时效性最高,是微妙级别。其次是 Kafka,是ms以内, ActiveMQ 和 RocketMQ 都是ms级的
  • ActiveMQ 和 RabbitMQ 是基于主从架构,可用性高, RocketMQ 和 Kafka 是分布式架构,可用性非常高
  • ActiveMQ 有较低概率丢失数据,RabbitMQ 基本不丢消息,RocketMQ 和 Kafka 可以通过参数优化做到不丢消息
  • ActiveMQ 的功能最完备,RabbitMQ 的并发能力强,性能极好,延时很低,RocketMQ 功能较完善,Kafka 功能较简单,主要支持简单的MQ功能,在大数据领域的实时计算及日志采集被大规模使用
  • RocketMQ 和 Kafka 社区活跃度高,ActiveMQ 和 RabbitMQ 社区活跃度较低

选型是需要综合考虑:可靠性、性能、吞吐量、消息有序性、是否会丢失消息等

消息队列之重复消费、顺序消费、分布式事务:

重复消费: 消费者集群如果重复消费同一条消息会导致业务异常,为了解决这个问题,我们需要保证接口幂等来消除重复消费引起的问题,幂等即在多次执行相同操作,产生的影响与第一次执行相同。

对于强校验的场景,我们可以加流水对账表来保证幂等性,即用流水对账表记录被消费的消息,如果再次来消息,先对比有没有被消费过,消费过的数据,直接返回。

对于弱校验场景,可以做缓存对比判断。

顺序消费: 对于同一个场景中多个消费者多条消息需要进行顺序消费的情况下,例如增改删操作需要保证顺序消费。或者审批流程的发起、通过、结束消息需要严格保证顺序。RocketMQ topic 内的队列机制可以保证 FIFO ,实现方式就是将消息同步发送到同一个队列中。此处只保证发送有序,消费有序由消费者自己保证。

分布式事务: 事务,是保证一系列操作,要么都成功,要么都回滚。分布式事务是在分布式系统中,保证一系列操作,要么都成功,要么都失败。

常见的分布式事务解决方案:

  • 2pc(两阶段提交),MySQL bin.log 和 redo.log提交
  • 3pc(三阶段提交)
  • TCC(Try、Confirm、Cancel)
  • 最大努力通知
  • XA
  • 本地消息表(ebay研发出的)
  • 半消息/最终一致性(RocketMQ)