1、为什么使用消息队列?
解耦、异步、削峰
2、消息队列有什么优缺点
优点:解耦、异步、削峰
缺点:系统可用性降低、系统复杂度提高、一致性问题
3、如何进⾏消息队列选型?
-
Kafka:
○ 优点: 吞吐量⾮常⼤,性能⾮常好,集群⾼可⽤。
○ 缺点:会丢数据,功能⽐较单⼀。
○ 使⽤场景:⽇志分析、⼤数据采集
-
RabbitMQ:
○ 优点: 消息可靠性⾼,功能全⾯。
○ 缺点:吞吐量⽐较低,消息积累会严重影响性能。erlang语⾔不好定制。
○ 使⽤场景:⼩规模场景
-
RocketMQ:
○ 优点:⾼吞吐、⾼性能、⾼可⽤,功能⾮常全⾯。
○ 缺点:开源版功能不如云上商业版。官⽅⽂档和周边⽣态还不够成熟。客户端只⽀持java。
○ 使⽤场景:⼏乎是全场景。
4、ActiveMQ、RabbitMQ、RocketMQ、Kafka比较
-
单机吞吐量: ActiveMQ、RabbitMQ 万级;RocketMQ、Kafka 10万级
-
topic数量对吞吐量影响:RocketMQ几百几千topic性能略微下降,Kafka从几十到几百性能急剧下降
-
时效性: RabbitMQ 微秒级别;ActiveMQ、RocketMQ、Kafka 毫秒级别
-
可用性:ActiveMQ、RabbitMQ主从架构,高可用;RocketMQ、Kafka分布式架构,可用性非常高
-
可靠性:ActiveMQ小概率丢数据;Rabbit几乎不丢;RocketMQ、Kafka通过配置可实现0丢失功能支持
-
功能完备度:ActiveMQ极其完备;RabbitMQ性能高延迟低;RocketMQ功能丰富且是分布式架构,易扩展;Kafka功能简单,适合特定场景。
5、RocketMQ
(1)RocketMQ组成部分(角色)有哪些?
-
生产者(Producer):负责产生消息,生产者向消息服务器发送由业务应用程序系统生成的消息。
-
消费者(Consumer):负责消费消息,消费者从消息服务器拉取信息并将其输入用户应用程序。
-
消息服务器(Broker):是消息存储中心,主要作用是接收来自 Producer 的消息并存储, Consumer从这里取得消息。
-
名称服务器(NameServer):用来保存 Broker 相关 Topic 等元信息并给 Producer ,提供 Consumer查找 Broker 信息。
(2)RocketMQ消费模式有几种?
集群消费
-
一条消息只会被同Group中的一个Consumer消费
-
多个Group同时消费一个Topic时,每个Group都会有一个Consumer消费到数据
广播消费
-
消息将对一个Consumer Group 下的各个 Consumer 实例都消费一遍。即即使这些 Consumer
属于同一个Consumer Group ,消息也会被 Consumer Group 中的每个 Consumer 都消费一
次
(3)RocketMQ如何保证消息的顺序消费?
生产者有序发送
生产者在投放消息的时候自定义投放策略,我们实现一个MessageQueueSelector接口,使用Hash取模法来保证同一个订单在同一个队列中就行了,即通过订单ID%队列数量得到该ID的订单所投放的队列在队列列表中的索引,然后该订单的所有消息都会被投放到这个队列中。
消费者有序消费
RockerMQ的MessageListener回调函数提供了两种消费模式,有序消费模式MessageListenerOrderly和并发消费模式MessageListenerConcurrently。
在消费的时候,还需要保证消费者注册MessageListenerOrderly类型的回调接口实现顺序消费,如果消费者采用Concurrently并行消费,则仍然不能保证消息消费顺序。
(4)RocketMQ如何保证消息不丢失?
Producer端
采取 send() 同步发消息,发送结果是同步感知的。
发送失败后可以重试,设置重试次数。默认3次。
Broker端
修改刷盘策略为同步刷盘。默认情况下是异步刷盘的。
集群部署
Consumer端
完全消费正常后在进行手动ack确认
(5)RocketMQ执行流程?
-
启动 Namesrv,Namesrv起 来后监听端口,等待 Broker、Producer、Consumer 连上来,相当于一个路由控制中心。
-
Broker 启动,跟所有的 Namesrv 保持长连接,定时发送心跳包。
-
收发消息前,先创建 Topic 。创建 Topic 时,需要指定该 Topic 要存储在 哪些 Broker上。也可以在发送消息时自动创建Topic。
-
Producer 发送消息。
-
Consumer 消费消息。
(6)消费者获取消息有几种模式?
消费者获取消息有两种模式:推送模式和拉取模式。
PushConsumer
推送模式(虽然 RocketMQ 使用的是长轮询)的消费者。消息的能及时被消费。使用非常简单,内部已处理如线程池消费、流控、负载均衡、异常处理等等的各种场景。
PullConsumer
拉取模式的消费者。应用主动控制拉取的时机,怎么拉取,怎么消费等。主动权更高。但要自己处理各种场景
(7)RocketMQ的事务消息是如何实现的
a. ⽣产者订单系统先发送⼀条half消息到Broker,half消息对消费者⽽⾔是不可⻅的
b. 再创建订单,根据创建订单成功与否,向Broker发送commit或rollback
c. 并且⽣产者订单系统还可以提供Broker回调接⼝,当Broker发现⼀段时间half消息没有收到任
何操作命令,则会主动调此接⼝来查询订单是否创建成功
d. ⼀旦half消息commit了,消费者库存系统就会来消费,如果消费成功,则消息销毁,分布式事
务成功结束
e. 如果消费失败,则根据重试策略进⾏重试,最后还失败则进⼊死信队列,等待进⼀步处理
6、如何保证消息队列的高可用
Rabbit:镜像集群
在镜像集群模式下,你创建的 queue,无论元数据还是 queue 里的消息都会存在于多个实例上,就是说,每个 RabbitMQ 节点都有这个 queue 的一个完整镜像,包含 queue 的全部数据的意思。然后每次你写消息到 queue 的时候,都会自动把消息同步到多个实例的 queue 上。
Kafka:基于分布式实现高可用,多个broker,多partion,多replica,leader读写,follower主动从leader处pull数据
7、如何保证消息不被重复消费?
上下游约定唯一标识
-
写库根据唯一键排重
-
写redis set天然排重
8、如何保证消息的可靠性传输?
消息可靠传输代表了两层意思,既不能多也不能少。
-
为了保证消息不多,也就是消息不能重复,也就是⽣产者不能重复⽣产消息,或者消费者不能重复消费消息
-
⾸先要确保消息不多发,这个不常出现,也⽐较难控制,因为如果出现了多发,很⼤的原因是⽣产者⾃⼰的原因,如果要避免出现问题,就需要在消费端做控制
-
要避免不重复消费,最保险的机制就是消费者实现幂等性,保证就算重复消费,也不会有问题,通过幂等性,也能解决⽣产者重复发送消息的问题
-
消息不能少,意思就是消息不能丢失,⽣产者发送的消息,消费者⼀定要能消费到,对于这个问题,就要考虑两个⽅⾯
-
⽣产者发送消息时,要确认broker确实收到并持久化了这条消息,⽐如RabbitMQ的confirm机制,Kafka的ack机制都可以保证⽣产者能正确的将消息发送给broker
-
broker要等待消费者真正确认消费到了消息时才删除掉消息,这⾥通常就是消费端ack机制,消费者接收到⼀条消息后,如果确认没问题了,就可以给broker发送⼀个ack,broker接收到ack后才会删除消息
9、Kafka如何保证消息的顺序性
在Kafka中Partition(分区)是真正保存消息的地方,发送的消息都存放在这里。Partition(分区)又存在于Topic(主题)中,并且一个Topic(主题)可以指定多个Partition(分区)。
在Kafka中,只保证Partition(分区)内有序,不保证Topic所有分区都是有序的。
所以 Kafka 要保证消息的消费顺序,可以有2种方法:
-
1个Topic(主题)只创建1个Partition(分区),这样生产者的所有数据都发送到了一个Partition(分区),保证了消息的消费顺序。
-
生产者在发送消息的时候指定要发送到哪个Partition(分区)。
10、RocketMQ的实现原理
RocketMQ由NameServer注册中⼼集群、Producer⽣产者集群、Consumer消费者集群和若⼲Broker (RocketMQ进程)组成,它的架构原理是这样的:
Broker在启动的时候去向所有的NameServer注册,并保持⻓连接,每30s发送⼀次⼼跳
Producer在发送消息的时候从NameServer获取Broker服务器地址,根据负载均衡算法选择⼀台服务器来发送消息
Conusmer消费消息的时候同样从NameServer获取Broker地址,然后主动拉取消息来消费
11、kafka的零拷贝原理
-
mmap机制
-
sendfile()
12、说一下 Kafka 中 Partition 分区副本的 Leader 选举算法
Kafka 首先会选择一个具有最新数据的副本作为新的 Leader,也就是 ISR 集合中的副本。其中,ISR(In-Sync Replica)是指与 Leader 同步的副本集合,它们的数据同步状态与 Leader 最接近,并且它们与 Leader 副本的网络通信延迟最小。
如果 ISR 集合中没有可用的副本,Kafka 会从所有副本中选择一个具有最新数据的副本作为新的 Leader。在这种情况下选举出来的 Leader,由于和原来老的 Leader 节点的数据存在较大的延迟,会造成数据丢失的情况
所以 Kafka 设计者把这个功能开关的选择交给了开发者,如果愿意接受这种情况,可以通过unclean.leader.election.enable 参数来设置。开启之后虽然会造成数据丢失,但是至少可以保证依然能对外提供服务,保证了可用性
13、大量消息积压,如何处理?
-
consumer出问题,首先修复consumer问题,恢复其消费速度。
-
新建10个queue,程序分发原来队列里面的数据到10个queue里面,10倍consumer机器,每一批消费一个queue,处理完成之后恢复原来架构。
14、如何设计一个消息队列?
可伸缩性,broker -> topic -> partition
可靠性,消息持久化,磁盘顺序写,数据零丢失方案
可用性,多副本 -> leader & follower -> broker 挂了重新选举 leader