消息组件
消息组件
1、常见的消息中间件有哪些
目前在市面上比较主流的消息中间件主要有,Kafka、ActiveMQ、RabbitMQ、RocketMQ 等这几种。
消息中间件一般用来在分布式系统中实现异步、削峰、解耦
2、消息模型
消息模型有队列模型和发布订阅模型。
队列模型每条消息只能被一个消费者消费,而发布/订阅模型就是为让一条消息可以被多个消费者消费而生的,当然队列模型也可以通过消息全量存储至多个队列来解决一条消息被多个消费者消费问题,但是会有数据的冗余。
发布/订阅模型兼容队列模型,即只有一个消费者的情况下和队列模型基本一致。
RabbitMQ
采用队列模型,RocketMQ
和Kafka
采用发布/订阅模型。
3、如何保证消息不丢失?
就我们市面上常见的消息队列而言,只要配置得当,我们的消息就不会丢。
消息的传递路径:生产者》Broker》消费者
在生产者端:生产者
需要处理好Broker
的响应,出错情况下利用重试、报警、日志记录等手段。这样就能保证在生产消息阶段消息不会丢失。
在Broker端:需要控制响应的时机,单机情况下是消息刷盘后返回响应,集群多副本情况下,即发送至两个副本及以上的情况下再返回响应。这样能保证在Broker端消息不会丢失
在消费者端:需要在执行完真正的业务逻辑之后再返回响应给Broker
。
要注意消息可靠性增强了,性能就下降了,等待消息刷盘、多副本同步后返回都会影响性能。因此还是看业务,例如日志的传输可能丢那么一两条关系不大,因此没必要等消息刷盘再响应。
4、如何处理重复消息?
接口保证幂等性、业务判断是否已处理过。
基本上就这么几个套路,真正应用到实际中还是得看具体业务细节。
5、如何保证消息的有序性?
全局有序:如果要保证消息的全局有序,首先只能由一个生产者往Topic
发送消息,并且一个Topic
内部只能有一个队列(分区)。消费者也必须是单线程消费这个队列。这样的消息就是全局有序的!一般情况下我们都不需要全局有序,即使是同步MySQL Binlog
也只需要保证单表消息有序即可。
部分有序:绝大部分的有序需求是部分有序,部分有序我们就可以将Topic
内部划分成我们需要的队列数,把消息通过特定的策略发往固定的队列中,然后每个队列对应一个单线程处理的消费者。这样即完成了部分有序的需求,又可以通过队列数量的并发来提高消息处理效率。
举个部分有序的业务场景比如订单的创建、支付、发货、收货:
拿RocketMQ来说,一个topic下有多个队列,为了保证发送有序,RocketMQ提供了MessageQueueSelector队列选择机制,我们可使用Hash取模法,让同一个订单发送到同一个队列中,再使用同步发送,只有同个订单的创建消息发送成功,再发送支付消息。这样,我们保证了发送有序。RocketMQ的topic内的队列机制,可以保证存储满足FIFO(First Input First Output 简单说就是指先进先出),剩下的只需要消费者顺序消费即可
6、如何处理消息堆积?
消息的堆积往往是因为生产者的生产速度与消费者的消费速度不匹配
7、推模式和拉模式
一般而言我们在谈论推拉模式的时候指的是 Comsumer 和 Broker 之间的交互。
推模式指的是消息从 Broker 推向 Consumer,即 Consumer 被动的接收消息,由 Broker 来主导消息的发送。
拉模式指的是 Consumer 主动向 Broker 请求拉取消息,即 Broker 被动的发送消息给 Consumer。
RocketMQ 和 Kafka 都选择了拉模式,RocketMQ 和 Kafka 都是利用“长轮询”来实现拉模式,消费者和 Broker 相互配合,拉取消息请求不满足条件的时候 hold 住,避免了多次频繁的拉取动作,当消息一到就提醒返回。
当然业界也有基于推模式的消息队列如 ActiveMQ。