MetaMQ 架构原理(转)

本文详细介绍了MetaMQ,一个分布式消息中间件,其架构原理、核心概念如消息生产者、消费者、Topic、分区等,并探讨了其存储、消息消费、可靠性和Zookeeper在元数据管理中的应用。MetaMQ不遵循JMS规范,仅支持发布订阅消费模型,所有消息均为持久性。文章还涉及了文件读写、通信框架和协议,以及高可用性和分布式事务支持。
摘要由CSDN通过智能技术生成

原创文章,转载请注明出处:http://jameswxx.iteye.com/blog/2034111

 

本来只是想看下metaq的文档,结果发现好乱,现在metaq其实有两个大分支了,一个是庄晓丹维护的已开源的,另外一个是淘宝内部的,本质结构原理没太大区别,只不过开源的已经去掉了对淘系相关的依赖。然后淘系的metaq已经到3.*版本了,但是文档比较乱,深入到细节时,发现好乱,一个点有好几种说法,火大,干脆自己看metaq的源码,有点意思,做个笔记记录下,怕我以后忘记了。有少量的章节和图片从内网拿来的,大部分是自己写的,记录下几个主要的点。

 

一:metaq是什么

metaq是一个分布式消息中间件,消息中间件是典型的生产者-消费者模型,核心作用是解耦,生产者和消费者彼此没有直接依赖,同步化解成了异步。metaq并没有遵循jms规范,jms规范体现在系统层面和api层面。

 

消费模型

例如jms定义了两种消息传递方式:

1 基于队列的点对点消费模型

2 基于发布/订阅的消费模型

Metaq只有发布订阅的消费方式。

消息类型

JMS定义的消息类型有TextMessage、MapMessage、BytesMessage、StreamMessage、ObjectMessage。Metaq只有一种类型:Message。

消息持久性

JMS定义两种持久性类型:

PERSISTENT 指示JMS provider持久保存消息,以保证消息不会因为JMS provider的失败而丢失。
NON_PERSISTENT 不要求JMS provider持久保存消息。

Metaq的消息都是持久性的

API

JMS定义了消息中间件的生产端api和消费端api,这些api都是约定的接口,都都被metaq无视了。

 

二:一些概念

消息生产者
负责产生消息并发送消息到meta服务器
消息消费者
负责消息的消费,meta采用pull模型,由消费者主动从meta服务器拉取数据并解析成消息并消费
Topic
消息的主题,由用户定义并在服务端配置。producer发送消息到某个topic下,consumer从某个topic下消费消息
分区
同一个topic下面还分为多个分区,如meta-test这个topic我们可以分为10个分区,分别有两台服务器提供,那么可能每台服务器提供5个分 区,假设服务器分别为0和1,则所有分区为0-0、0-1、0-2、0-3、0-4、1-0、1-1、1-2、1-3、1-4
Message
消息,负载用户数据并在生产者、服务端和消费者之间传输
Broker
就是meta的服务端或者说服务器,在消息中间件中也通常称为broker。
消费者分组(Group)
消费者可以是多个消费者共同消费一个topic下的消息,每个消费者消费部分消息。这些消费者就组成一个分组,拥有同一个分组名称,通常也称为消费者集群
Offset
消息在broker上的每个分区都是组织成一个文件列表,消费者拉取数据需要知道数据在文件中的偏移量,这个偏移量就是所谓offset。Offset是绝对偏移量,服务器会将offset转化为具体文件的相对偏移量

 

 

 

三:总体结构图

 

 

 

 

 

四:消息存储

消息中间件中消息堆积是很常见,这要求broker具有消息存储的能力,消息存储结构决定了消息的读写性能,对整体性能有很大影响,metaq是分布式的,多个borker可以为一个topic提供服务,一个topic下的消息分散存储在多个broker,它们是多对多关系。

如下图

 

消息定义

id
消息的唯一id,系统自动产生,用户无法设置,在发送成功后由服务器返回,发送失败则为0。
topic
消息的主题,订阅者订阅该主题即可接收发送到该主题下的消息,必须
data
消息的有效载荷,也就是消息内容,meta永远不会修改消息内容,你发送出去是什么样子,接收到就是什么样子。
attribute
消息属性,一个字符串,可选。发送者可设置消息属性来让消费者过滤。

 

物理文件
metaq将消息存储在本地文件中,每个文件最大大小为1G,如果写入新的消息时,超过当前文件大小,则会自动新建一个文件。文件名称为起始字节大小,例如,假设文件最大尺寸为1k,有三个文件,则文件名如
下(长度为20位,不足补0):
00000000000000000000
00000000000000001024
00000000000000002048
即使一个broker为多个topic服务,这些topic的消息都存储同一个文件组中,消息顺序写入,永远都是当前文件在写,其他文件只读。

索引文件
弄清消息的物理存储后,也许我们会有一个疑问:如何读取指定topic的当前消息?的确,仅仅只存储消息是无法做到这个的,所以metaq还有索引文件,类似数据库的索引,但是有很大区别。broker将消息存储到文件后,会将该消息在文件的物理位置,消息大小,消息类型封装成一个固定大小的数据结构,暂且称这个数据结构为索引单元吧,大小固定为16k,消息在物理文件的位置称为offset。

 

 

 

索引单元结构

 

offset size
messateType
8字节
4字节 4字节

 

多个索引单元组成了一个索引文件,索引文件默认固定大小为20M,和消息文件一样,文件名是

 

起始字节位置,写满后,产生一个新的文件。

 

 

逻辑分区
一个逻辑分区实际上是一组索引文件。一个topic在一个broker上可以有多个逻辑分区,默认为1,但可自由配置。为什么会有多个分区的情况?逻辑分区的作用不仅仅是通过索引提供快速定位消息的功能,它还跟整个metaq的集群有很大的关系。

逻辑结构图

 

 

五:集群与负载均衡

Topic分布

一个topic可以分布在多台broker上,具体体现就是多个broker配置了这个topic,并且最少有一个分区。假如有一个topic名为”t1”,两个broker:b1,b2;每个borker都为t1配置了两个分区。那么t1一共有4个分区:b1-1,b1-2,b2-1,b2-2。生产者和消费者对topic发布消息或消费消息时,目的地都是以分区为单位。当一个topic消息量逐渐变大时,可以将topic分布在更多的borker上。某个broker上的分区数越多,意味着该borker承担更繁重的任务,分区数可以认为是权重的表现形式。

生产者
生产者在通过zk获取分区列表之后,会按照brokerId和分区号的顺序排列组织成一个有序的分区列表,发送的时候按照从头到尾循环往复的方式选择一个分区来发送消息。这是默认的分区策略,考虑到我们的broker服务器软硬件配置基本一致,默认的轮询策略已然足够。如果你想实现自己的负载均衡策略,可以实现上文提到过的PartitionSelector接口,并在创建producer的时候传入即可。在broker因为重启或者故障等因素无法服务的时候,producer通过zookeeper会感知到这个变化,将失效的分区从列表中移除做到fail over。因为从故障到感知变化有一个延迟,可能在那一瞬间会有部分的消息发送失败。

消费者
消费者的负载均衡会相对复杂一些。我们这
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值