mq消息中间件面前突击

参考文章:Rocketmq原理&最佳实践

一、面答

主讲:Rocketmq

1、mq优势: 流量缓冲(削峰填谷)、系统解耦、性能提升、蓄流压测

2、rocketmq主要优势:事务型消息、支持18个延迟消息级别、消息失败重发(指定次数和间隔时间)、消费端根据tag过滤

3、rocketmq和kafka对比:

  精简,面试mq必答题

指标rocketMqkafka
应用场景非日志可靠传输消息(订单、充值、交易)日志消息传输(日志收集、监控、常规消息系统)
语言javascala
持久化/部署磁盘文件、单机/集群(高可用、分布式、主从)磁盘文件、单机/集群(高可用、分布式、主从)
集群管理命名空间zookeeper
选主方式不支持自动选主,同brokername,brokerid=0为master,其他未slave通过zk在isr中自动选举leader
自动切换不支持,master失效后可从slave消费,master无法恢复,异步消费可能会出现消息丢失允许n-1个副本失效,失效后自动选举
性能10字节,单机7w/s,3台集群,12w/s10字节,百万每秒
复制备份同步双写
异步复制:slave线程从master拉取
消息->leader.log<--pull--flower-->ack,log-->维护同步列表,落后太多被删除
消息投递支持pull,push两种模式,毫秒级毫秒级,消费端轮询时间决定

总结优劣:

太懒了,直接上图:

二、RocketMq集群概述

1、架构图

a)name server  :无状态,可集群部署,节点之间不进行通信

b)Broker : 分为master和slave。 brokerName相同则为同一集群,brokerId=0 为master,非0为slave。master:slave  = 1:n;

                  broker与name server集群中所有节点建立长连接,定时(每隔30s)注册Topic信息到所有Name Server。Name Server定时(每隔10s)扫描所有存活broker的连接,如果Name Server超过2分钟没有收到心跳,则Name Server断开与Broker的连接。

c)producer :与name server集群中任一节点建立长连接,定期(30秒)拉取topic信息,并与topic的master建立长连接。Producer完全无状态,可集群部署。

d)Consumer:与name server集群中其中一个节点建立长连接,定期从name server拉取topic路由信息,并向提供topic的master,slave 建立长连接,可从master 和slave 订阅消息,可配置策略。

当Consumer得到master宕机通知后,转向slave消费,slave不能保证master的消息100%都同步过来了,因此会有少量的消息丢失。但是一旦master恢复,未同步过去的消息会被最终消费掉。

消费者对列是消费者连接之后(或者之前有连接过)才创建的。我们将原生的消费者标识由 {IP}@{消费者group}扩展为 {IP}@{消费者group}{topic}{tag}

producer 和 Consumer 共性:

每隔30s从Name server获取topic的最新队列情况,这意味着Broker不可用时,最多最需要30s才能感知。

每隔30s(由ClientConfig中heartbeatBrokerInterval决定)向所有关联的broker发送心跳,Broker每隔10s扫描所有存活的连接,若某个连接2分钟内没有发送心跳数据,则关闭连接;

 三、Rocketmq如何支持分布式事务消息

A(存在DB操作)、B(存在DB操作)两方需要保证分布式事务一致性,通过引入中间层MQ,A和MQ保持事务一致性(异常情况下通过MQ反查A接口实现check),B和MQ保证事务一致(通过重试),从而达到最终事务一致性。

1. MQ与DB一致性原理(两方事务)

 

2、多系统之间数据一致性(多方事务)

四、 顺序消息

1. 顺序消息缺陷

发送顺序消息无法利用集群Fail Over特性消费顺序消息的并行度依赖于队列数量队列热点问题,个别队列由于哈希不均导致消息过多,消费速度跟不上,产生消息堆积问题遇到消息失败的消息,无法跳过,当前队列消费暂停。

2. 原理

produce在发送消息的时候,把消息发到同一个队列(queue)中,消费者注册消息监听器为MessageListenerOrderly,这样就可以保证消费端只有一个线程去消费消息。

注意:把消息发到同一个队列(queue),不是同一个topic,默认情况下一个topic包括4个queue

3. 扩展

可以通过实现发送消息的对列选择器方法,实现部分顺序消息。

举例:比如一个数据库通过MQ来同步,只需要保证每个表的数据是同步的就可以。解析binlog,将表名作为对列选择器的参数,这样就可以保证每个表的数据到同一个对列里面,从而保证表数据的顺序消费

五、延迟消息

延迟消息的时间不是任意时间片,而是仅支持18个固定的时间段,默认的配置是messageDelayLevel=1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h,分别代表延迟level1-level18,对应的延迟时间可以通过配置修改,下面谈谈具体它是怎么实现的

1 所有的延迟消息到达broker后,会存放到SCHEDULE_TOPIC_XXX的topic下(这个topic比较特殊,对客户端是不可见的,包括使用rocketmq-console,也查不到这个topic)

2 SCHEDULE_TOPIC_XXX这个topic下存在18个队列,每个队列中存放的消息都是同一个延迟级别消息

3 broker端启动了一个timer和timerTask的任务,定时从此topic下拉取数据,如果延迟时间到了,就会把此消息发送到指定的topic下,完成延迟消息

 

六、 最佳实践

1. Producer

1) Topic

一个应用尽可能用一个Topic,消息子类型用tags来标识,tags可以由应用自由设置。只有发送消息设置了tags,消费方在订阅消息时,才可以利用tags 在broker做消息过滤。

2) key

每个消息在业务层面的唯一标识码,要设置到 keys 字段,方便将来定位消息丢失问题。服务器会为每个消息创建索引(哈希索引),应用可以通过 topic,key来查询这条消息内容,以及消息被谁消费。由于是哈希索引,请务必保证key 尽可能唯一,这样可以避免潜在的哈希冲突。

//订单Id

String orderId= "20034568923546";

message.setKeys(orderId);

3) 日志

消息发送成功或者失败,要打印消息日志,务必要打印 send result 和key 字段。

4) send

send消息方法,只要不抛异常,就代表发送成功。但是发送成功会有多个状态,在sendResult里定义。

SEND_OK:消息发送成功

FLUSH_DISK_TIMEOUT:消息发送成功,但是服务器刷盘超时,消息已经进入服务器队列,只有此时服务器宕机,消息才会丢失

FLUSH_SLAVE_TIMEOUT:消息发送成功,但是服务器同步到Slave时超时,消息已经进入服务器队列,只有此时服务器宕机,消息才会丢失

SLAVE_NOT_AVAILABLE:消息发送成功,但是此时slave不可用,消息已经进入服务器队列,只有此时服务器宕机,消息才会丢失

2. Consumer

1) 幂等

RocketMQ使用的消息原语是At Least Once,所以consumer可能多次收到同一个消息,此时务必做好幂等。

2) 日志

消费时记录日志,以便后续定位问题。

3) 批量消费

尽量使用批量方式消费方式,可以很大程度上提高消费吞吐量

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值