MetaQ使用心得

〇、信息来源:
 
一、MetaQ是什么?
     (一)、师从kafka ,是一款高可用,可无限水平扩展的消息中间件。核心为:
        1、他使用拉模型的消息队列。
        2、集群可水平扩展。
        3、能够保证顺序。该特征可应用于例如流计算或Mysql的binlog同步等。以及保证如订单顺序一致性。
     (二)、发展历程:
        1、Metamorphosis 1.x版本应该是庄晓丹(([email protected]))和誓嘉(新浪微博: vintage-wang )共同开发。后庄晓丹从阿里离开。
        2、2.0版本开始,产品名称由“Metamorphosis”改为“Metaq”。主要由 誓嘉维护并开源
        3、现在3.0之后称作RocketMQ,但阿里对此开源程度热情降低,网上资料较少,例如Github上没有文档,需要申请后才可以获取文档。不知道是不是跟阿里云商业化有关。
     (三)、产品特点:
        1、保证消息顺序:消息有序指的是一类消息消费时,能按照发送的顺序来消费。例如:一个订单产生了3条消息,分别是订单创建,订单付款,订单完成。消费时,要按照这个顺序消费才能有意义。但是同时订单之间是可以并行消费的。由此带来的特征:
            (1)、通过Offset递增进行访问数据,缺乏KV存储具有的update能力,如果要支持事务,必须引入类似于KV存储的模块才可以。
            (2)、不能保证消息不重复:为了追求高性能,并不保证此特性,要求在业务上进行去重,也就是说消费消息要做到幂等性。Metaq虽然不能严格保证不重复,但是正常情况下都不会出现重复发送、消费情况,只有网络异常,Consumer启停等异常情况下会出现消息重复。
        2、所有消息均必须落盘。与标准JMS不同。
        3、基于拉模型。注:似乎Meta2.X版本支持推模型
        4、其他:不支持分布式事务。而阿里Notify支持;消息类型只有一种字符串类型。与标准JMS不同;不支持JMS API;只支持发布订阅模式。与标准JMS不同。个人理解,该模式似乎更应称作“生产、消费者”模型。而Notify才更偏向于发布订阅模式;不支持优先级调度:由于Metaq所有消息都是持久化的,所以如果按照优先级来排序,开销会非常大,因此Metaq没有特意支持消息优先级,但是可以通过变通的方式实现类似功能,即单独配置一个优先级高的队列,和一个普通优先级的队列, 将不同优先级发送到不同队列即可。
     (四)、核心概念:
        1、Producer:消息生产者,负责产生消息,一般由业务系统负责产生消息。
        2、 Consumer:消息消费者,负责消费消息,一般是后台系统负责异步消费。注:Meta2.x也支持使用Push模型进行同步消息处理,但不太推荐。
        3、Broker:消息中转角色,负责存储消息,转发消息,一般也称为Server。在JMS规范中称为Provider。
        4、主动消费:Consumer主动向Broker发起获取消息请求,控制权完全在于Consumer应用。即Pull模型。
        5、被动消费:Consumer注册一个Callback接口,由Metaq后台自动从Broker接收消息,并回调Callback接口。即Push模型。
        6、普通顺序消息:消费消息的顺序要同发送消息的顺序一致,在Metaq中,主要指的是局部顺序,即一类消息为满足顺序性,必须Producer单线程顺序发送,且发送到同一个队列,这样Consumer就可以按照Producer发送的顺序去消费消息。
        7、Message Queue:在Metaq中,所有消息队列都是持久化,长度无限的数据结构,所谓长度无限是指队列中的每个存储单元都是定长,访问其中的存储单元使用Offset来访问,offset为java long类型,64位,理论上在100年内不会溢出,所以认为是长度无限,另外队列中只保存最近几天的数据,之前的数据会按照过期时间来删除。在Metaq2.x之前版本,队列也称为“分区”,两者描述的是一个概念。但是按照2.x的实现,使用队列描述更合适。
     (五)、核心概念图:

 

        

 

 

 

        (1)、按照阿里说法,一个Broker支持万级Message Queue。

        (2)、如果不采用广播方式,一个队列中的某个消息只能被一个Consumer处理,处理后,Consumer自己管理的offset进行便宜。查找下一个消息。

        (3)、每个队列维持自己一套“索引”和“物理存储”。

二、怎么用MetaQ?



        (一)、Producer:在OnException中需要将失败消息记录到本地,新起线程不断尝试重发。
                注:即Producer自身也有消息日志机制;需要使用幂等策略(可参照ePay策略),保障重发也不会发生故障;可能需要做处理,保障与此关联的其他消息如订单的后续操作不能执行。
        (二)、Consumer:同样应该是处理异常后尝试,并保障后续关联消息不能执行。
                ??Executor怎么做异步,还没有理解透。
 
三、MetaQ核心原理(消息存储及读取)
     (一)、如何落盘:
        1、落盘采用两种方式:异步和同步。异步性能高,写完PAGECACHE(操作系统维护,应该是磁盘自身的缓冲区)直接返回,后续Broker后台异步批量写入磁盘,但不能保证全部消息不丢失。



 

 

        2、所有数据单独存储到一个物理队列,完全顺序写(串行方式刷盘),随机读。
        3、复制策略:目前仅支持异步复制,即类似于MySQL主从模式;不支持同步双写。未来版本会通过同步双写技术来完全避免单点,同步双写势必会影响性能,适合对消息可靠性要求极高的场合,例如与Money相关的应用。
 
    (二)、如何查找消息:使用“索引文件”(固定大小,可能在内存)+“物理文件”(物理存储)方式查找。如下图,先找索引,再找物理消息。

        

 

 

 

          

四、怎么做集群?
        

 
    1、异步复制后,部分消费者可以直接使用从节点;MetaQ2.X似乎还不支持同步复制。
    2、ZK节点,目录查找举例如下:
        (1)、生产者查找主Broker:/meta/brokers/topics(固定)/hello(Topic名称)/m1(Broker名称)-m(主Broker)
        (2)、消费者查找Offset:/meta/consumers(固定)/hellogroup(消费者组)/offsets(固定)/t1(Topic名称)/b1(Broker名称)-1(分区名称)
    3、负载均衡:
        (1)、生产者负载均衡:metaq发送消息的时候,生产者在发送消息的时候必须选择一台broker上的一个分区来发送消息,因此metaq在运行过程中,会把所有broker和对应的分区信息全部注册到ZK指定节点上,默认的策略是一个依次轮询的过程,生产者在通过ZK获取分区列表之后,会按照brokerId和partition的顺序排列组织成一个有序的分区列表,发送的时候按照从头到尾循环往复的方式选择一个分区来发送消息。注意:在broker因为重启或者故障等因素无法服务的时候,producer通过zookeeper会感知到这个变化,将失效的分区从列表中移除做到fail over。因为从故障到感知变化有一个延迟,可能在那一瞬间会有部分的消息发送失败。
        (2)、消费负载均衡:在消费过程中,一个消费者会消费一个或多个分区中的消息,但是一个分区只会由一个消费者来消费。MetaQ的消费策略是:
            1、每个分区针对同一个group只挂载一个消费者。
            2、如果同一个group的消费者数目大于分区数目,则多出来的消费者将不参与消费。
            3、如果同一个group的消费者数目小于分区数目,则有部分消费者需要额外承担消费任务。
            4、在某个消费者故障或者重启等情况下,其他消费者会感知到这一变化(通过 zookeeper watch消费者列表),然后重新进行负载均衡,保证所有的分区都有消费者进行消费。
 
 
 
 
 

猜你喜欢

转载自ituski.iteye.com/blog/2227379