目录
消息中间件的区别?
为什么要使用 MQ?
2.3 RocketMQ 由哪些角色组成,每个角色作用和特点是什么?
2.4 RocketMQ 消费模式有几种?
2.5 RocketMQ 如何做负载均衡?
2.6 消息重复消费如何解决?
2.7 如何让 RocketMQ 保证消息的顺序消费
2.8 RocketMQ 如何保证消息不丢失?
2.9 RocketMQ 的消息堆积如何处理
2.10 RocketMQ 如何实现分布式事务?
2.11 任何一台 Broker 突然宕机了怎么办?
消息中间件的区别? 为什么要使用 MQ?
因为项目比较大,做了分布式系统,所有远程服务调用请求都是同步执行经常出问题,所以引入了 mq
2.3 RocketMQ 由哪些角色组成,每个角色作用和特点是什么?
生产者(Producer):负责产生消息,生产者向消息服务器发送由业务应用程序系统生成的消息。
消费者(Consumer):负责消费消息,消费者从消息服务器拉取信息并将其输入用户应用程序。
消息服务器(Broker):是消息存储中心,主要作用是接收来自 Producer 的消息并存储, Consumer 从这里取得消息。
名称服务器(NameServer ):用来保存 Broker 相关 Topic 等元信息并给Producer ,提供 Consumer 查找 Broker 信息。
消费模型由 Consumer 决定,消费维度为 Topic。
集群消费
1. 一条消息只会被同 Group 中的一个 Consumer 消费
2. 多个 Group 同时消费一个 Topic 时,每个 Group 都会有一个 Consumer 消费到数据
广播消费
消息将对一 个 Consumer Group 下的各个 Consumer 实例都消费一遍。即即使这些 Consumer 属于同一个 Consumer Group ,消息也会被 Consumer Group 中的每个Consumer 都消费一次。
通过 Topic 在多 Broker 中分布式存储实现。
(1)producer 端
发送端指定 message queue 发送消息到相应的 broker,来达到写入时的负载均衡。
提升写入吞吐量,当多个 producer 同时向一个 broker 写入数据的时候,性能会下降
消息分布在多 broker 中,为负载消费做准备
默认策略是随机选择:
producer 维护一个 index
每次取节点会自增
index 向所有 broker 个数取余
自带容错策略
(2) consumer 端
采用的是平均分配算法来进行负载均衡。
其他负载均衡算法
1.平均分配策略(默认)(AllocateMessageQueueAveragely)
2、环形分配策略(AllocateMessageQueueAveragelyByCircle)
3、手动配置分配策略(AllocateMessageQueueByConfig)
4、机房分配策略(AllocateMessageQueueByMachineRoom)
5、一致性哈希分配策略(AllocateMessageQueueConsistentHash)
追问:当消费负载均衡 consumer 和 queue 不对等的时候会发生什么?
Consumer 和 queue 会优先平均分配,如果 Consumer 少于 queue 的个数,则会存在部分 Consumer 消费多个 queue 的情况,如果 Consumer 等于 queue 的个数,那就是一个 Consumer 消费一个 queue,如果 Consumer 个数大于 queue 的个数,那么会有部分 Consumer 空余出来,白白的浪费了。
2.6 消息重复消费如何解决?影响消息正常发送和消费的重要原因是网络的不确定性。
出现原因
正常情况下在 consumer 真正消费完消息后应该发送 ack,通知 broker 该消息已正常消费,从 queue 中剔除,当 ack 因为网络原因无法发送到 broker,broker 会认为词条消息没有被消费,此后会开启消息重投机制把消息再次投递到 consumer。
消费模式:在 CLUSTERING 模式下,消息在 broker 中会保证相同 group 的 consumer 消费一次,但是针对不同 group 的 consumer 会推送多次
解决方案:
数据库表:处理消息前,使用消息主键在表中带有约束的字段中 insert
Map:单机时可以使用 map 做限制,消费时查询当前消息 id 是不是已经存在
Redis:使用分布式锁。
你们线上业务用消息中间件的时候,是否需要保证消息的顺序性?
如果不需要保证消息顺序,为什么不需要?假如我有一个场景要保证消息的顺序,你们应该如何保证?
首先多个 queue 只能保证单个 queue 里的顺序,queue 是典型的 FIFO,天然顺序。多个 queue 同时消费是无法绝对保证消息的有序性的。
所以总结如下:
同一 topic,同一个 QUEUE,发消息的时候一个线程去发送消息,消费的时候 一个线程去消费一个 queue 里的消息。
追问:怎么保证消息发到同一个 queue?
Rocket MQ 给我们提供了 MessageQueueSelector 接口,可以自己重写里面的接口,实现自己的算法,举个最简单的例子:判断 i % 2 == 0,那就都放到 queue1 里,否则放到 queue2 里。
首先在如下三个部分都可能会出现丢失消息的情况:
Producer 端、Broker 端、Consumer 端
2.8.1 Producer 端如何保证消息不丢失
1、采取 send()同步发消息,发送结果是同步感知的。
2、发送失败后可以重试,设置重试次数。默认 3 次。
producer.setRetryTimesWhenSendFailed(10);
3、集群部署,比如发送失败了的原因可能是当前 Broker 宕机了,重试的时候会发送到其他 Broker 上。
2.8.2 Broker 端如何保证消息不丢失
修改刷盘策略为同步刷盘。默认情况下是异步刷盘的。 flushDiskType = SYNC_FLUSH
集群部署,主从模式,高可用。
2.8.3 Consumer 端如何保证消息不丢失
完全消费正常后在进行手动 ack 确认。
2.9 RocketMQ 的消息堆积如何处理1. 如果可以添加消费者解决,就添加消费者的数据量.
2、如果出现了 queue,但是消费者多的情况。可以使用准备一个临时的 topic,同时创建一些 queue,在临时创建一个消费者来把这些消息转移到 topic 中,让消费者消费。
1、生产者向 MQ 服务器发送 half 消息。
2、half 消息发送成功后,MQ 服务器返回确认消息给生产者。
3、生产者开始执行本地事务。
4、根据本地事务执行的结果(UNKNOW、commit、rollback)向 MQ Server 发送提交或回滚消息。
5、如果错过了(可能因为网络异常、生产者突然宕机等导致的异常情况)提交/回滚消息,则 MQ 服务器将向同一组中的每个生产者发送回查消息以获取事务状态。
6、回查生产者本地事物状态。
7、生产者根据本地事务状态发送提交/回滚消息。
8、MQ 服务器将丢弃回滚的消息,但已提交(进行过二次确认的 half 消息)的消息将投递给消费者进行消费。
Half Message : 预 处 理 消 息 , 当 broker 收 到 此 类 消 息 后 , 会 存 储 到RMQ_SYS_TRANS_HALF_TOPIC 的消息消费队列中
检查事务状态:Broker 会开启一个定时任务,消费 RMQ_SYS_TRANS_HALF_TOPIC 队列中的消息,每次执行任务会向消息发送者确认事务执行状态(提交、回滚、未知),如果是未知,Broker 会定时去回调在重新检查。
超时:如果超过回查次数,默认回滚消息。
也就是他并未真正进入 Topic 的 queue,而是用了临时 queue 来放所谓的 half message,等提交事务后才会真正的将 half message 转移到 topic 下的 queue。
Broker 主从架构以及多副本策略。Master 收到消息后会同步给 Slave,这样一条消息就不止一份了,Master 宕机了还有 slave 中的消息可用,保证了 MQ 的可靠性和高可用性。而且 Rocket MQ4.5.0 开始就支持了 Dlegder 模式,基于 raft 的,做到了真正意义的 HA。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)