分布式消息队列可以提供应用解耦、流量消峰、消息分发、保证最终一致性、方便动态扩容等功能,已经成为大型互联网服务架构里标配的中间件。
RocketMq具有 单机吞吐量:十万级别,吞吐量高 时效性:ms级别 等特点,深受大家的喜爱!
之前面试的过程中就遇到面试官问我你是如果使用RocketMq,RocketMq内部结构等等!如果之前不了解RocketMq,看完这篇文章你会对RocketMq有一个很大的理解!
如果你正在学习RocketMq一定要认真看完,真的很有用!
推荐一本书 《RocketMQ实战与原理解析》
RocketMq集群部署示意图
RocketMQ由四部分组成:Producer、Consumer、Broker和NameServer
1.NameServer是如何与Broker进行协调的?
每个broker启动都得向所有的NameServer进行注册,Broker会跟每个NameServer都建立一个TCP长连接,Broker会每隔30s给所有的NameServer发送心跳,告诉每个NameServer自己目前还活着,然后NameServer会每隔10s运行一个任务,去检查一个各个Broker的最近一次心跳时间,如果某个Broker超过120s都没发送心跳了,那么就认为这个Broker已经挂掉了。
2.Master Broker是如何将消息同步给Slave Broker的?
RocketMq的Master-Slave模式采取的是Slave Broker不停的发送请求到Master Broker去拉取消息。采用的是Pull模式拉取消息。
3.作为消费者的系统再获取消息的时候,是从Master Broker获取消息,还是从Slave Broker获取消息?
作为消费者的系统在获取消息的时候会发送请求到Master Broker上去,请求获取一批消息,此时Master Broker是会返回一批消息给消费者系统,然后Master Broker在返回消息给消费者系统的时候,会根据当时Master Broker的负载情况和Slaver Broker的同步情况,向消费者系统建议下一次拉取消息的时候是从Master Broker拉取还是从Slave Broker拉取。
4.RocketMq4.5版本后是如何实现Master Broker 与Slave Broker切换的?
RocketMq4.5版本后支持了一种机制叫做 Dledger,是基于Raft协议实现的一个机制,一旦Master Broker宕机,既可以在多个Slave Broker中,通过Dledger技术和Raft协议算法进行leader选举,直接将一个Slave Broker选举为新的Master Broker。
5.RocketMq对事务的支持
1)发送方向RocketMQ发送“待确认”消息(half消息)。
2)RocketMQ将收到的“待确认”消息持久化成功后,向发送方回复消息已经发送成功,此时第一阶段消息发送完成。
3)发送方开始执行本地事件逻辑。
4)发送方根据本地事件执行结果向RocketMQ发送二次确认(Commit或是Rollback)消息,RocketMQ收到Commit状态则将第一阶段消息标记为可投递,订阅方将能够收到该消息;收到Rollback状态则删除第一阶段的消息,订阅方接收不到该消息。
5)如果出现异常情况,步骤4)提交的二次确认最终未到达RocketMQ,服务器在经过固定时间段后将对“待确认”消息发起回查请求。
6)发送方收到消息回查请求后(如果发送一阶段消息的Producer不能工作,回查请求将被发送到和Producer在同一个Group里的其他Producer),通过检查对应消息的本地事件执行结果返回Commit或Rollback状态。
6.RocketMQ支持两种消息模式:Clustering和Broadcasting。
1.在Clustering模式下,同一个ConsumerGroup(GroupName相同)里的每个Consumer只消费所订阅消息的一部分内容,同一个ConsumerGroup里所有的Consumer消费的内容合起来才是所订阅Topic内容的整体,从而达到负载均衡的目的。
2.在Broadcasting模式下,同一个ConsumerGroup里的每个Consumer都能消费到所订阅Topic的全部消息,也就是一个消息会被多次分发,被多个Consumer消费。
7.RocketMQ保证消息不丢失,但有可能造成消息重复,你们业务是如果保证数据不重复消费的?
消息重复一般情况下不会发生,但是如果消息量大,网络有波动,消息重复就是个大概率事件。比如Producer有个函数setRetryTimesWhenSendFailed,设置在同步方式下自动重试的次数,默认值是2,这样当第一次发送消息时,Broker端接收到了消息但是没有正确返回发送成功的状态,就造成了消息重复。
解决消息重复有两种方法:第一种方法是保证消费逻辑的幂等性(多次调用和一次调用效果相同);另一种方法是维护一个已消费消息的记录,消费前查询这个消息是否被消费过。这两种方法都需要使用者自己实现。
8.RocketMQ的具体消息存储结构是怎样的呢?
RocketMQ消息的存储是由ConsumeQueue和CommitLog配合完成的,消息真正的物理存储文件是CommitLog,ConsumeQueue是消息的逻辑队列,类似数据库的索引文件,存储的是指向物理存储的地址。每个Topic下的每个Message Queue都有一个对应的ConsumeQueue文件
CommitLog以物理文件的方式存放,每台Broker上的CommitLog被本机器所有ConsumeQueue共享,在CommitLog中,一个消息的存储长度是不固定的,RocketMQ采取一些机制,尽量向CommitLog中顺序写,但是随机读。ConsumeQueue的内容也会被写到磁盘里作持久存储。
9.消息在通过Producer写入RocketMQ的时候,有两种写磁盘方式,同步刷新,异步刷新
1.异步刷盘方式:在返回写成功状态时,消息可能只是被写入了内存的PAGECACHE,写操作的返回快,吞吐量大;当内存里的消息量积累到一定程度时,统一触发写磁盘动作,快速写入。
2.同步刷盘方式:在返回写成功状态时,消息已经被写入磁盘。具体流程是,消息写入内存的PAGECACHE后,立刻通知刷盘线程刷盘,然后等待刷盘完成,刷盘线程执行完成后唤醒等待的线程,返回消息写成功的状态
—————END—————
推荐阅读:
最近面试BAT,整理一份面试资料《Java面试BAT通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。
获取方式:关注公众号并回复 java 领取,更多内容陆续奉上。
明天见(。・ω・。)ノ♡