RocketMq总结
MQ的主要特点为解耦、异步、削峰。或者说
1、系统解耦
2、流量削峰
3、异步分发
用于减少数据库压力的业务场景,其中RocketMQ的核心组件概念如下:
Producer:生产发送消息
Broker:存储Producer发送过来的消息
Consumer:从Broker拉取消息并进行消费
NameServer:为Producer或Consumer路由到Broker
RocketMq
集群工作流程
1、启动NameServer,等待Broker,Producer,Consumer连接,NameServer相当于注册中心,用于路由控制。
2、Broker启动,跟所有NameServer保持长连接,心跳机制,定时发送心跳包,心跳包包含当前Broker信息(IP+端口)以及存储所有的Topic信息。
心跳:
心跳间隔:每隔30秒(此时间无法更改)向所有nameserver发送心跳,心跳包含了自身的topic配置信息。
心跳超时:nameserver每隔10秒钟(此时间无法更改),扫描所有还存活的broker连接,若某个连接2分钟内(当前时间与最后更新时间差值超过2分钟,此时间无法更改)没有发送心跳数据,则断开连接。
断路:
时机:broker挂掉;心跳超时导致nameserver主动关闭连接
动作:一旦连接断开,nameserver会立即感知,更新topic与队列的对应关系,但不会通知生产者和消费者
3、producer,单个producer与其中一台nameserver建立长连接,定时查询topic配置信息,轮询时间,每隔30秒(非心跳机制)从nameserver获取所有topic的最新队列情况。
单个producer与所有broker建立长连接。
心跳:
默认情况下,生产者每隔30秒向所有broker发送心跳,该时间由DefaultMQProducer的heartbeatBrokerInterval参数决定,可手动配置。broker每隔10秒钟(此时间无法更改),扫描所有还存活的连接,若某个连接2分钟内(当前时间与最后更新时间差值超过2分钟,此时间无法更改)没有发送心跳数据,则关闭连接。
4、consumer,单个消费者和一台nameserver保持长连接,定时查询topic配置信息,如果该nameserver挂掉,消费者会自动连接下一个nameserver,直到有可用连接为止,并能自动重连。
默认情况下,消费者每隔30秒从nameserver获取所有topic的最新队列情况,这意味着某个broker如果宕机,客户端最多要30秒才能感知。该时间由DefaultMQPushConsumer的pollNameServerInteval参数决定,可手动配置。
单个消费者和该消费者关联的所有broker保持长连接。
默认情况下,消费者每隔30秒向所有broker发送心跳,该时间由DefaultMQPushConsumer的heartbeatBrokerInterval参数决定,可手动配置。broker每隔10秒钟(此时间无法更改),扫描所有还存活的连接,若某个连接2分钟内(当前时间与最后更新时间差值超过2分钟,此时间无法更改)没有发送心跳数据,则关闭连接,并向该消费者分组的所有消费者发出通知,分组内消费者重新分配队列继续消费。
运行原理:
面试题:
1、如何保证顺序消费。
顺序消费实际上有两个核心点,一个是生产者有序存储,另一个是消费者有序消费。
RocketMQ支持生产者在投放消息的时候自定义投放策略,我们实现一个MessageQueueSelector接口,使用Hash取模法来保证同一个订单在同一个队列中就行了,即通过订单ID%队列数量得到该ID的订单所投放的队列在队列列表中的索引,然后该订单的所有消息都会被投放到这个队列中。
消费者端使用MessageListenerOrderly。
2、事务消息
消息监听器主要是实现TransactionListener接口,然后需要重写下面两个方法:
- executeLocalTransaction:执行本地事务;
- checkLocalTransaction:回查本地事务状态,根据这次回查的结果来决定此次事务是提交还是回滚;
问:rocketmq 事务消息 实现两个方法,本地事务,回查本地状态,当本地事务执行成功,服务器挡掉,此时回查无响应 此事务消息是回滚还是提交?
答:在这种情况下,如果本地事务执行成功但服务器在回查时无响应,RocketMQ事务消息会被认为是不确定状态。通常情况下,RocketMQ会根据超时时间来判断是否要回滚该事务消息。如果在一定时间内未收到回查响应,RocketMQ会将该事务消息标记为“Rollback Only”,最终会回滚该事务消息,以确保数据的一致性。
3、保证消息不丢失
三部分保证消息不丢失:producer,broker,consumer。
消息生产者:
同步发送:Producer 向 broker 发送消息,阻塞当前线程等待 broker 响应 发送结果。
异步发送:Producer 首先构建一个向 broker 发送消息的任务,把该任务提交给线程池,等执行完该任务时,回调用户自定义的回调函数,执行处理结果。
Oneway 发送:Oneway 方式只负责发送请求,不等待应答,Producer 只负责把请求发出去,而不处理响应结果。
我们在调用 producer.send 方法时,不指定回调方法,则默认采用同步发送消息的方式,这也是丢失几率最小的一种发送方式。
producer 消息发送方式虽然有 3 种,但为了减小丢失消息的可能性尽量采用同步的发送方式,同步等待发送结果,利用同步发送 + 重试机制 + 多个 master 节点,尽可能减小消息丢失的可能性
从broker:
同步刷盘的策略
主从支持同步双写
在 broker 端,消息丢失的可能性主要在于刷盘策略和同步机制。
RocketMQ 默认 broker 的刷盘策略为异步刷盘,如果有主从,同步策略也默认的是异步同步,这样子可以提高 broker 处理消息的效率,但是会有丢失的可能性。因此可以通过同步刷盘策略 + 同步 slave 策略 + 主从的方式解决丢失消息的可能。
从消费者consumer:
consumer 默认提供的是 At least Once 机制
Consumer 先 pull 消息到本地,消费完成后,才向服务器返回 ack。
消费消息重试机制
consumer 端要保证消费消息的可靠性,主要通过 At least Once + 消费重试机制保证。