1.RocketMQ研究

部署架构

部署RocketMQ的时候,会部署两种角色,一个是注册中心NameServer,另一个是Broker

在这里插入图片描述
消费端只要配置好nameserver即可,如果nameserver采用了集群模式,只要配置其中一个就可以;

消费者从nameserver中获取到broker列表,然后与broker建立长连接;

存储模型

在这里插入图片描述
一个topic中的数据,可能会存在多个broker中;

而每个broker中,真正存储消息的是commitLog,而队列queue中存放的是消息的引用;
一个broker中会有多个队列;

单个Queue也可能会存储多个topic

详解Broker

Broker与Name Server关系

1)连接 :单个broker和所有的Name Server保持长连接
2)心跳
心跳间隔:每隔30秒向所有NameServer发送心跳,心跳包含了自身的Topic配置信息。
心跳超时:NameServer每隔10秒,扫描所有还存活的Broker连接,若某个连接2分钟内没有发送心跳数据,则断开连接。
3)断开:当Broker挂NameServer会根据心跳超时,主动关闭连接,并更新topic和队列的映射关系; 但是不会通知生产者和消费者

这会有什么影响呢?

因为生产者和消费者是每隔30s从nameserver中获取所有的topic的最新队列,所以当broker宕机以后,生产者和消费者最多要30s才会感知,在感知前,从该broker中拉取消息,或者发往该broker中的消息都会失败

Consumer和Broker关系

1)连接:单个消费者与该消费者关联所有broker保持长连接

负载均衡

集群消费模式下,一个消费集群中的多台消费者会消费同一个topic的所有队列,一个队列只会被一个消费集群中的一个消费者消费;

当该消费者宕机以后,会被该消费组中其他消费者继续消费;

可用性

RocketMq提供了Master/Slave结构,Slave定时从Master上读取消息;
当Master宕机后,Slave上的消息可能是全的,也可能部分消息还没有来得及同步过来;

这个时候Slave就会对外提供服务,但是不支持消息写入 ,所以当master宕机以后,可能会造成消息丢失的情况;

当时当master恢复过来以后,未同步过去的消息会继续被消费;

Producer

Producer和Name Server

1)连接 单个Producer和一台NameServer保持长连接,如果该NameServer挂掉,生产者会自动连接下一个NameServer,直到有可用连接为止,并能自动重连。
2)轮询时间 默认情况下,生产者每隔30秒从NameServer获取所有Topic的最新队列情况,这意味着某个Broker如果宕机,生产者最多要30秒才能感知,在此期间,
发往该broker的消息发送失败。
3)心跳 与nameserver没有心跳

因为consumer和producer和nameserver都保持有长连接,所以mq控制台就可以看到消费者和生产者的上线和下线

与broker关系

连接 单个生产者和该生产者关联的所有broker保持长连接。


RocketMq消费模式

消费模式由consumer定义,消费维度是topic

启动生产者和消费者的时候,要定义ID(例如producerId或者consumerId),而这个ID就是组ID;
1)集群模式

一个消息只能被同一个group中的一个consumer消费
如果多个group同事消费一个topic,那每个group中就有且只有一个consumer中消费到该数据

2)广播模式
消息将会被订阅了该主题的所有的消费者消费到,不管该消费者是否在一个组里

RocketMQ没有真正的push,全部都是pull,虽然有 org.apache.rocketmq.client.impl.consumer.DefaultMQPushConsumerImp类,但是它消费消息也是采用了长轮询,pull的方式消费消息的,简直就是小骗子

消息是如何分配到多个broker上的

默认策略是随机选择

  • producer维护一个index
  • 每次取节点会自增
  • index向所有broker个数取余
  • 自带容错策略

其他实现:
SelectMessageQueueByHash
hash的是传入的args
SelectMessageQueueByRandom
SelectMessageQueueByMachineRoom 没有实现
也可以自定义实现MessageQueueSelector接口中的select方法

MessageQueue select(final List mqs, final Message msg, final Object arg);

消费者负载消费的策略

producer如何保证消息只发送一次

consumer如何保证消息只消费一次

如果发送方同一个报文发送多次,可能消息的messageID不同,但是内容相同;

如果因为网络原因,消费方已经消费了消息,但是ack失败,相同的消息(同一个messageID)会被重复消费;

对于内容相同,但是messageID不同的,我们可以创建IGNORE_ROW_ON_DUPKEY_INDEX(表名(字段1,字段2,。。))方式进行插入,主键相同的自动忽略

对于messageID相同的,如果是单机,可以采用单机时可以使用

map ConcurrentHashMap -> putIfAbsent guava cache

如果是分布式

分布式锁

如何保证消息的顺序

同一个queue中的消息本身就是有顺序的,对于不同queue中的消息无法实现消息的顺序消费;

例如,要求一个订单的生成,扣减库存,扣减费用,要顺序消费;

我们可以给订单生成订单号
根据订单号hash算出队列序号,这样就能保证一个订单的消息肯定都在一个队列中了;

如何保证消息不丢失

首先从三个方面来说
1)生产者
发送方式有同步发送,异步发送,单向发送
为了消息不丢失建议采用同步发送 什么时候返回?同步到丛机上再返回?还是发送到master上就返回呢?
设置重试次数,默认重试发送3次;
2)broker端

  • 修改刷盘策略为同步刷盘,默认是异步刷盘
  • 集群部署,主从模式,高可用
broker集群方式:
1.单master模式
2.多master模式
3.多master,多slave,异步刷盘
4.多master,多slave,同步刷盘---主备都写成功,向应用返回成功;
优点:数据不丢失,master宕机后,消息无延迟;
缺点:复制性能低,发送单个消息的返回RT会略高。
主宕机以后,slave无法自动切换为主机,只能提供读的功能
  1. consumer端
    完全消费正常后再手动ack

rocketMQ消息堆积如何处理

首先要确认原因,可能是

  • 程序bug
  • 网络原因 ,消费者无法连接上nameserver,无法获取最新的topic的队列集合,要不就无法连接broker了

比如 broker集群扩容,导致新的broker id没有对消费者开放权限,导致新增的broker机器上的消息无法被消费;

  • 或者是生产者多,而消费者少,导致消费能力跟不上

追问:如果Consumer和Queue不对等,上线了多台也在短时间内无法消费完堆积的消息怎么办?

  • 准备一个临时的topic queue的数量是堆积的几倍 queue分布到多Broker中
  • 上线一台Consumer做消息的搬运工,把原来Topic中的消息挪到新的Topic里,不做业务逻辑处理,只是挪过去
  • 上线N台Consumer同时消费临时Topic中的数据 改bug
  • 恢复原来的Consumer,继续消费之前的Topic

已经消费的消息会被保存7天,7天以后会如何处理?

没有被消费的消息不存在超时删除的情况,RocketMq中的消息只有在comitLog被删除的时候才会被消失

消费失败的消息,重试16次,会进入死信队列,然后呢?什么时候清理

如果消息总是消费失败,那它后面的消息就一直无法被消费吗?不是说同一个队列中的消息,消费顺序是先进先出么

分布式事务如何实现的

默认消费组线程数量多少,默认一次性拉取多少条消息

发送消息的时候,如何尽量避免可能会出错的broker

producerId和consumerId的作用是什么?会和topic关联吗?一个消费组只能订阅一个topic吗?

mq控制台怎么就感知到某跳消息消费失败了呢?

消费者什么情况下会从broker中获取offeset呢?根据查看阿里云的rocketmq的日志ons.log,发现,消费者一端是每隔一会就会从mq服务上拉取offset信息;


最全架构图

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值