消息组件
消息组件
1、常见的消息中间件有哪些
目前在市面上比较主流的消息中间件主要有,Kafka、ActiveMQ、RabbitMQ、RocketMQ 等这几种。
消息中间件一般用来在分布式系统中实现异步、削峰、解耦
2、消息模型
消息模型有队列模型和发布订阅模型。
队列模型每条消息只能被一个消费者消费,而发布/订阅模型就是为让一条消息可以被多个消费者消费而生的,当然队列模型也可以通过消息全量存储至多个队列来解决一条消息被多个消费者消费问题,但是会有数据的冗余。
发布/订阅模型兼容队列模型,即只有一个消费者的情况下和队列模型基本一致。
RabbitMQ
采用队列模型,RocketMQ
和Kafka
采用发布/订阅模型。
3、如何保证消息不丢失?
就我们市面上常见的消息队列而言,只要配置得当,我们的消息就不会丢。
消息的传递路径:生产者》Broker》消费者
在生产者端:生产者
需要处理好Broker
的响应,出错情况下利用重试、报警、日志记录等手段。这样就能保证在生产消息阶段消息不会丢失。
在Broker端:需要控制响应的时机,单机情况下是消息刷盘后返回响应,集群多副本情况下,即发送至两个副本及以上的情况下再返回响应。这样能保证在Broker端消息不会丢失
在消费者端:需要在执行完真正的业务逻辑之后再提交位移给Broker
。
要注意消息可靠性增强了,性能就下降了,等待消息刷盘、多副本同步后返回都会影响性能。因此还是看业务,例如日志的传输可能丢那么一两条关系不大,因此没必要等消息刷盘再响应。
4、如何处理重复消息?
接口保证幂等性、业务判断是否已处理过。具体方式有下面3种:
- Redis中设置全局ID
- MySQL主键约束
- 更新前根据主键查询数据库是否已处理
基本上就上面这么几个套路,真正应用到实际中还是得看具体业务细节。
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。
8、介绍一下Kafka的ISR机制
ISP,是In-Sync Replicas,同步副本的意思,主要用来确保数据可靠性和一致性的。
在Kafka中,每个主题分区可以有多个副本,ISR是与主副本保持同步的副本集合。
当消息发送到主题的某个分区时,首先被写入主副本(leader),然后主副本将所有的消息同步给ISR中的其它副本,只有当所有的副本都成功接收并确认了消息之后,主副本才认为消息成功提交。
9、介绍一下Kafka的重平衡机制
Kafka的重平滑机制是指在消费者组中新增或删除消费者时,Kafka集群会重新分配主题分区给各个消费者,以保证每个消费者消费的分区数量尽可能均衡。这个机制的目的是实现消费者的负载均衡和高可用性。
重平衡的3个触发条件分别是:
- 消费者组的成员数量发生变化。
- 订阅主题数量发生变化
- 订阅主题的分区数量发生变化。
重平衡的步骤大致如下:
- 暂停所有消费:集群暂停所有消费者的消息拉取操作,以确保在重平衡期间不会出现消息丢失或者消息重复消费。
- 计算分区分配方案:集群根据当前消费者组的消费数量和主题分区数量,计算出每个消费者应分配的分区列表,最大程度保证分区的负载均衡。
- 通知消费者:集群将分配方案发给每个消费者,请求他们重新加入消费者组。
- 恢复消费:集群恢复所有消费者的拉取操作,允许它们开始消费分配到的分区。
重平衡期间,会暂停所有消费者实例的消费,直到重平衡操作结束。这就是STW现象,目前并没有好的办法来解决,只能尽量避免它的发生。
10、kafka的数据存储模型
Kafka有Topic和Partition两个概念,一个Topic可以有多个Partition。在实际存储的时候,Topic+Partition对应一个文件夹,例如如果有4个Topic,每个Topic有5个Partition,那么一共会有4*5=20个文件夹。而在文件夹的下一层是采用SegmentFile的存储方式进行存储的。
Segment File的大概意思是:将大文件拆分为小文件来存储,这样一个大文件就变成了一段一段(Segment段)。这样的好处是IO加载速度快。每个Segment段具体由index文件和log文件组成,而index文件是为了加速查找,有索引的功能。log文件中存放的是完整的消息记录。
示例:
00000000000000000000000.index
00000000000000000000000.log
00000000000000000002222.index
00000000000000000002222.log