👆 这是第 341 篇不掺水的原创,想要了解更多,请戳下方卡片关注我们吧~
至 2010 年,随着阿里业务的快速发展,急需一款支持顺序消息,拥有海量消息堆积能力的消息 Meta Q 1.0 在 2011 年诞生。
到 2012 年, Meta Q 已经发展到了 Meta Q 3.0 ,并抽象出了通用的消息引擎 Rocket MQ。随后,将 Rocket MQ 进行了开源。
到 2016 年, Meta Q 在当年双十一承载了万亿级消息的流转,跨越了一个新的里程碑,同时 Rocket MQ 进入 Apache 孵化。
Topic:标识一类消息的逻辑名字,消息的逻辑管理单位。无论消息生产还是消费,都需要指定 Topic。
Tag:Rocket MQ 支持给在发送的时候给 Topic 打 Tag,同一个 Topic 的消息虽然逻辑管理是一样的。但是消费 Topic1 的时候,如果你订阅的时候指定的是 Tag A,那么 Tag B 的消息将不会投递。
Message Queue:简称 Q。一个 Topic 将有若干个 Q。若 Topic 同时创建在不通的 Broker,则不同的 Broker 上都有若干 Q,消息将物理地存储落在不同 Broker 结点上,具有水平扩展的能力。
Offset:可以认为一条逻辑的 Message Queue 是无限长的数组。一条消息进来下标就会涨 1,而这个数组的下标就是 Offset。
Max Offset:这个 Offset 实际上是最新消息的 Offset + 1,即:下一条消息的 Offset。
Min Offset:标识现存在的最小 Offset。而由于消息存储一段时间后,消费会被物理地从磁盘删除,Message Queue 的 Min Offset 也就对应增长。这意味着比 Min Offset 要小的那些消息已经不在 Broker 上了,无法被消费。
Consumer Offset:表示的是下次拉取的 Offset 位置。
存储当前集群所有 Brokers 信息、Topic 跟 Broker 的对应关系。
集群最核心模块,主要负责 Topic 消息存储、消费者的消费位点管理(消费进度)。只有 Master 才能进行写入操作,Slave 从 Master 中同步数据。
生产者。发送消息的客户端角色。发送消息的时候需要指定 Topic。Producer 完全无状态,可集群部署。
消费者,通常有两种实现,分别为 Push Consumer 和 Pull Consumer,通常我们采用 Push 的方式为主, Pull 的为辅的来进行消息的消费。
单个 Broker 跟所有 Name Sever 保持心跳请求,心跳间隔为30秒,心跳请求中包括当前 Broker 所有的 Topic 信息。Name Sever 会反查 Broker 的心跳信息,如果某个 Broker 在2分钟之内都没有心跳,则认为该 Broker 下线,调整 Topic 跟 Broker 的对应关系。但此时 Name Sever 不会主动通知 Producer、Consumer 有 Broker 宕机。
刷盘策略:Rocket MQ 的所有消息都是持久化的,先写入系统 Page Cache,然后刷盘,可以保证内存不磁盘都有一份数据,访问时,直接从内存读取。
异步刷盘: 举例:现有 SAS 15000 转磁盘测试顺序写文件,速度可以达到 300M 每秒左右,而线上的网卡一般都为千兆网卡,速度最快可达 128M 每秒, 写磁盘速度明显快于数据网络入口速度,那么刷盘的迕度肯定可以跟上消息的写入速度。
同步刷盘:和异步的唯一区别是异步写完 Page Cache 直接返回,而同步是等待刷盘完成之后再返回。
消费者启动时需要指定 Name Sever 地址,与其中一个 Name Sever 建立长连接。消费者每隔 30 秒从 Name Sever 获取所有 Topic 的最新队列情况,这意味着某个 Broker 如果宕机,客户端最多要 30 秒才能感知。连接建立后,从 Name Sever 中获取当前消费 Topic 所涉及的 Broker,直连 Broker。
和 Name Sever 的心跳检测和 Broker 类似。
消费者消费模式
负载均衡:消费者端的负载均衡,就是集群消费模式下,同一个 ID 的所有消费者实例平均消费该 Topic 的所有队列。
拉取流程:Consumer 端每隔一段时间主动向 Broker 发送拉消息请求,Broker 在收到 Pull 请求后,如果有消息就立即返回数据,Consumer 端收到返回的消息后,再回调消费者设置的 Listener 方法。如果 Broker 在收到 Pull 请求时,消息队列里没有数据,Broker 端会阻塞请求直到有数据传递或超时才返回。
虽然每个 Topic 下面有很多 Message Queue,但是 Message Queue 本身并不存储消息。真正的消息存储会写在 Commit Log 的文件,Message Queue 只是存储 Commit Log 中对应的位置信息,方便通过 Message Queue 找到对应存储在 Commit Log 的消息。不同的 Topic,Message Queue 都是写到相同的 Commit Log 文件,也就是说 Commit Log 完全的顺序写。
消息存储在 Commit Log 之后,的确是会被清理的,但是这个清理只会在以下任一条件成立才会批量删除消息文件(Commit Log):
注意:若磁盘空间达到危险水位线(默认90%),出于保护自身的目的,Broker 会拒绝写入服务。
如果你觉得这篇内容对你挺有启发,我想邀请你帮我两件小事
1.点个「在看」,让更多人也能看到这篇内容(点了「在看」,bug -1 😊)
招贤纳士
政采云技术团队(Zero),Base 杭州,一个富有激情和技术匠心精神的成长型团队。规模 500 人左右,在日常业务开发之外,还分别在云原生、区块链、人工智能、低代码平台、中间件、大数据、物料体系、工程平台、性能体验、可视化等领域进行技术探索和实践,推动并落地了一系列的内部技术产品,持续探索技术的新边界。此外,团队还纷纷投身社区建设,目前已经是 google flutter、scikit-learn、Apache Dubbo、Apache Rocketmq、Apache Pulsar、CNCF Dapr、Apache DolphinScheduler、alibaba Seata 等众多优秀开源社区的贡献者。
如果你想改变一直被事折腾,希望开始折腾事;如果你想改变一直被告诫需要多些想法,却无从破局;如果你想改变你有能力去做成那个结果,却不需要你;如果你想改变你想做成的事需要一个团队去支撑,但没你带人的位置;如果你想改变本来悟性不错,但总是有那一层窗户纸的模糊……如果你相信相信的力量,相信平凡人能成就非凡事,相信能遇到更好的自己。如果你希望参与到随着业务腾飞的过程,亲手推动一个有着深入的业务理解、完善的技术体系、技术创造价值、影响力外溢的技术团队的成长过程,我觉得我们该聊聊。任何时间,等着你写点什么,发给 zcy-tc@cai-inc.com