RocketMQ的学习

一、基本概念

        Message (消息)

                生产和消费的基本单位,生产者生产的一条数据就是一条Message,消费者消费的一条数据就是一条Message。

                一条Message必须属于某一种Topic

        Topic (主题)

                可以理解为一级分类,某种Message的集合。生产者生产的是车,消费者消费的是车,这个车就是Topic,而Message就是车下具体的车实体。

        Tag (标签)

                可以理解为二级分类,Topic是所有车的集合,Tag就可以是轿车、越野车、跑车等等再细分车种的集合。

        Queue (队列)

                存储Message的物理实体,一个Topic可以有多个Queue,Queue存储着该Topic的Message。一个Topic中的Queue也被称为该Topic的分区。

        消息标识

                生产者生产Message的时候回产生一个msgId,且可以携带具有业务标识的Key,以方便对消息的查询。

                消息到达Broker后,会生成一个offsetMsgId。

SendResult [sendStatus=SEND_OK, msgId=7F0000012D5414DAD5DC562EC9050047, offsetMsgId=C0A8CA8000002A9F00000000000F51E7, messageQueue=MessageQueue [topic=someTopic, brokerName=localhost.localdomain, queueId=3], queueOffset=92]


二、系统架构

 Producer (生产者)

                Provider生产者就是生产Message的对象,同一个生产者可以生产不同Topic的Message。

                在集群模式下,生产者会通过负载均衡,轮询同一个Topic下的所有Queue,将消息平均发送到每个Queue中。

        

 消息的生产  

                Producer可以将消息写入到某Broker中的某Queue中,其经历了如下过程:

                    1. Producer发送消息之前,会先向NameServer发出获取 消息Topic的路由信息 的请求                 

                    2. NameServer返回该Topic的路由表Broker列表。

                        路由表:实际是一个MapkeyTopic名称,value是一个QueueData实例列表。QueueData并不 是一个Queue对应一个QueueData,而是一个Broker中该Topic的所有Queue对应一个 QueueData。即,只要涉及到该TopicBroker,一个Broker对应一个QueueDataQueueData中 包含brokerName。简单来说,路由表的keyTopic名称,value则为所有涉及该TopicBrokerName列表。

                        Broker列表:Broker列表:其实际也是一个MapkeybrokerNamevalueBrokerData。一个Broker对应一 个BrokerData实例,对吗?不对。一套brokerName名称相同的Master-Slave小集群对应一个 BrokerDataBrokerData中包含brokerName及一个map。该mapkeybrokerIdvalue为该 broker对应的地址。brokerId0表示该brokerMaster,非0表示Slave

                     3. Producer根据代码中指定的Queue选择策略,从Queue列表中选出一个队列,用于后续存储消息

                     4. Producer向选择出的Queue所在的Broker发出RPC请求,将消息发送到选择出的Queue。

消费者 (Consumer) 

                消费者就是对消息队列中的消息进行消费。

                同一个消费者组只能消费同一个Topic下的消息。

                同一个消费者组中不同的消费者不能对同一个Queue进行消费。

                不同消费者组的消费者可以对同一个Topic下的消息进行消费。

                消费者在消费消息的负载均衡体现在将同一个Topic下的所有Queue平均分配给同一个消费者组下的消费者。例如有七个消息队列,四个消费者。那么前三个消费者可以消费两个消息队列,第四个消费者消费一个队列。

                消费者组中消费者数量应该>=消息队列的数量,因为如果消费者数量大于消息队列的数量,多出来的消费者也分配不到消息队列进行消费。

NameServer

                NameServer是一个BrokerTopic路由的注册中心,支持Broker的动态注册与发现。

       路由注册

                NameServer是无状态的,NameServer集群中,不同的节点之间是不通信的。在Broker启动的时候会通过轮询的方式,对NameServer列表进行轮询,和每个NameServer进行长连接,发送注册请求。每个NameServer内部都维护着一个Broker列表,保存着每个broker的路由信息。

                Broker通过心跳机制,每隔30S将自己最新的数据信息通过心跳包的方式上报给NameServer,以此来维护长连接。

Broker

                一台服务器就可以当作一个Broker,Broker充当着消息中转角色,负责存储消息转发消息BrokerRocketMQ系统中负责接收并存储从生产者发送来的消息,同时为消费者的拉取请求作准备。Broker同时也存储着消息相关的元数据,包括 消费者组消费进度偏移offset、主题、队列等

         消息的存储

        RocketMQ中的消息存储在本地文件系统中,这些相关文件默认在当前用户主目录下的store目录中。        

         abort:该文件在Broker启动后会自动创建,正常关闭Broker,该文件会自动消失。若在没有启动Broker的情况下,发现这个文件是存在的,则说明之前Broker的关闭是非正常关闭。

        checkpoint:其中存储着commitlogconsumequeueindex文件的最后刷盘时间戳。

        commitlog:其中存放着commitlog文件,而消息是写在commitlog文件中的。

                commitlog目录中存放着很多的mappedFile文件,当前Broker中的所有消息都是落盘到这mappedFile文件中的。

        需要注意的是,一个Broker中仅包含一个commitlog目录,所有的mappedFile文件都是存放在该目录中 的。即无论当前Broker中存放着多少Topic的消息,这些消息都是被顺序写入到了mappedFile文件中的。也就是说,这些消息在Broker中存放时并没有被按照Topic进行分类存放。

        mappedFile文件内容由一个个的消息单元构成。每个消息单元中包含消息总长度MsgLen、消息的物理 位置physicalOffset、消息体内容Body、消息体长度BodyLength、消息主题TopicTopic长度 TopicLength、消息生产者BornHost、消息发送时间戳BornTimestamp、消息所在的队列QueueId、消息在Queue中存储的偏移量QueueOffset等近20余项消息相关属性。

        config:存放着Broker运行期间的一些配置数据。

        consumequeue:其中存放着consumequeue文件,队列就存放在这个目录中。

                为了提高效率,会为每个Topic~/store/consumequeue中创建一个目录,目录名为Topic名称。在该 Topic目录下,会再为每个该TopicQueue建立一个目录,目录名为queueId。每个目录中存放着若干 consumequeue文件,consumequeue文件是commitlog的索引文件,可以根据consumequeue定位到具体的消息。

                每个consumequeue文件可以包含30w个索引条目,每个索引条目包含了三个消息重要属性:消息在mappedFile文件中的偏移量CommitLog Offset、消息长度、消息Taghashcode值。                

        index:其中存放着消息索引文件 indexFile。
        
        lock:运行期间使用到的全局资源锁。

        消息写入 :

                        Broker根据queueId,获取到该消息对应索引条目要在consumequeue目录中的写入偏移量,即 QueueOffset。

                        将queueId、queueOffset 等数据,与消息一起封装为消息单元。
                        将消息单元写入到commitlog。
                        同时,形成消息索引条目。
                        将消息索引条目分发到相应的consumequeue。
                       
        值得注意的是,ConsumeQueue是逻辑消费队列,它指向的是Broker中store文件下的具体的ConsumeQueue文件,也就是物理地址。而ConSumeQueue文件下又是不同Topic名字命名的Queue文件,Topic文件下就是具体的Queue,这些Queue中是一个个的索引条目,索引条目记录着记录着CommitLog offset,而CommitLog是真正储存着消息的地方,里面是一个个消息单元,消息单元里储存着真实的消息和各种相关的信息等。

           

工作流程

                1.启动NameServer,NameServer开始监听,等待Producer,Consumer,Broker的连接

                2.启动Broker,对NameServer列表进行轮询并注册。

                3.Producer在发送Message前可以创建Topic,也可以在发送时创建Topic。创建Topic时可以指定该Topic可以存储在哪些Broker上,Topic和Broker的关系也会注册到NameServer中。

                   Producer在发送Message时会和NameServer集群中的某一个NameServer建立长连接,获得NameServer上Broker的路由信息,将Message发送到相应的Broker和Topic下的Queue中。Producer会将路由信息缓存到本地,每隔30s重新拉取一次的路由信息。

                4.Consumer在消费Message时会和NameServer集群中的某一台NameServer建立长连接,获得需要消费的Topic的路由信息,随后和相应的Broker进行连接,对消息进行消费。Consumer会向Broker发送心跳确保Broker的状态。


集群

        

        复制策略

                同步复制:消息写入Master之后,Master会将消息同步到Slave后才向Producer返回ACK。

                异步复制:消息写入Master之后,Master无需等到将消息同步到Slave才返回ACK,Master会直接返回ACK。

        刷盘策略

                同步刷盘:消息写入Broker中的PageCache后,会等到消息持久化到磁盘中,才算刷盘成功。

                异步刷盘:消息写入Broker中的PageCache后,不用等到消息持久化到磁盘中。

       

                        

                    

                

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值