敖丙思维导图-RocketMQ+Zookeeper

本文深入探讨了RocketMQ的基础组成,包括消息生产者、消费者、代理服务器和名字服务,重点讲解了RocketMQ的消费保证、顺序消息、去重机制和分布式事务。同时,介绍了Zookeeper的选举机制、数据一致性保障以及在分布式系统中的应用。文章揭示了RocketMQ和Zookeeper如何协同工作,保证数据的一致性和系统的稳定性。
摘要由CSDN通过智能技术生成


在这里插入图片描述

RocketMq

基础组成

在这里插入图片描述

消息生产者(Producer

  1. 同步发送 - 需要Broker返回确认信息 (重要通知消息)
  2. 异步发送 - 需要Broker返回确认信息 (链路耗时较长而对响应时间敏感)
  3. 单向发送 (可靠性要求并不高)

消息消费者(Consumer) - ACK机制是发生在Consumer端

消费模型由Consumer决定,消费维度为Topic。

  1. 集群消费(一条消息只会被同Group中的一个Consumer消费)
  2. 广播消费(消息将对一 个Consumer Group 下的各个 Consumer 实例都消费一遍。)

RocketMQ没有真正意义的push,都是pull。push采用的是长轮询机制

  1. pull(拉取式消费)主动调用Consumer的拉消息方法从Broker服务器拉消息、主动权由应用控制。
  2. push(推动式消费-长轮询机制)Broker收到数据后会主动推送给消费端,该消费模式一般实时性较高。(难以根据消费者的状态控制推送速率,适用于消息量不大、消费能力强要求实时性高的情况下。)

代理服务器(Broker Server

  1. 消息中转角色,负责存储消息、转发消息。
  2. 每个Broker节点,在启动时,都会遍历NameServer列表,与所有的NameServer建立长连接,注册自己的信息,之后定时上报

从物理结构上看 Broker 的集群部署方式有四种:
单 Master
多 Master
单台机器宕机期间,该机器上未被消费的消息在机器恢复之前不可订阅,消息实时性会受影响。
多 Master 多 Slave(异步复制)
消息采用异步复制方式,主备之间有毫秒级消息延迟。这种方式优点是消息丢失的非常少,且消息实时性不会受影响,Master 宕机后消费者可以继续从 Slave 消费,中间的过程对用户应用程序透明,不需要人工干预,性能同多 Master 方式几乎一样。缺点是 Master 宕机时在磁盘损坏情况下会丢失极少量消息。
多 Master多 Slave(异步双写
消息采用同步双写方式,主备都写成功才返回成功。优点是数据与服务都没有单点问题,Master 宕机时消息无延迟,服务与数据的可用性非常高。缺点是性能相对异步复制方式略低,发送消息的延迟会略高。

名字服务(Name Server)-(路由管理,路由注册,服务发现)

RocketMq中的NameServer是一个无状态(zookeeper有状态)的命名服务(相关组件的状态在内存中),类似于dubbo中的zookeeper。生产者或消费者能够通过NameServer查找各主题相应的Broker IP列表。多个Namesrve实例组成集群,但相互独立,没有信息交换

一般NameServer先启动,broker后启动,启动后向所有的NameServer注册,produce发送消息时,会先从NameServer获取可用的broker地址,根据负载算法选择一个并发送。

主题(Topic) - 每个主题包含若干条消息,每条消息只能属于一个主题。
Topic是个抽象的概念,每个Topic底层对应N个queue,而数据也真实存在queue上的。

消费保证

  • 发送成功后返回consume_success
  • 回溯消费

RocketMQ顺序消息

大部分逻辑依赖客户端,也就是Producer和Consumer。

  1. RocketMQ的做法是有顺序关系的消息都发送到同一个queue上,自然他们也会存到同一个broker上。根据之前讲的broker消息的存储逻辑,同一个queue的消息,先到的肯定放在前面,所以只要客户端在发送的时候使用单线程,发完一条再发另一条,消息在broker上保存的顺序自然也是按发送的顺序。
  2. Broker不知道消息的状态,那就把保证顺序这件事交给Consumer,因为第一步中有顺序关系的消息已经在同一个queue里了,consumer拿消息的时候本来也是按照存的顺序来的,所以Broker不需要做任何特殊逻辑。

RocketMQ去重

MsgId

  • ip地址决定了分布式作业环境下生产的id值唯一
  • 进程id决定了单机上多个客户端实例间生产的id值唯一
  • count作为原子Integer类型,决定了单实例运行时高并发下生产的值唯一
  • time 乃当前时间戳 - 当月开始时间戳的long值,保证应用月内重启不会重复。
    offsetMsgId
    服务端ip地址+服务端消息的物理分区偏移量来达到唯一值id。

1、极为严谨的业务必须业务幂等。
2、宽松业务可以考虑使用OffsetMsgId作为去重id。

在这里插入图片描述

Rocketmq分布式事务

分布式系统中的事务可以使用TCC(Try、Confirm、Cancel)、2pc来解决分布式系统中的消息原子性。

Prepared阶段(预备阶段)
该阶段主要发一个消息到rocketmq,但该消息只储存在commitlog中,但consumeQueue中不可见,也就是消费端(订阅端)无法看到此消息。
commit/rollback阶段(确认阶段)
该阶段主要是把prepared消息保存到consumeQueue中,即让消费端可以看到此消息,也就是可以消费此消息。

1、在扣款之前,先发送预备消息 (第一步先给 Broker 发送事务消息即半消息,并且 RocketMQ 的发送方会提供一个反查事务状态接口,如果一段时间内半消息没有收到任何操作请求,那么 Broker 会通过反查接口得知发送方事务是否执行成功,然后执行 Commit 或者 RollBack 命令)
2、发送预备消息成功后,执行本地扣款事务
3、扣款成功后,再发送确认消息
4、消息端(加钱业务)可以看到确认消息,消费此消息,进行加钱
在这里插入图片描述

  • 如果发送预备消息成功,执行本地事务成功,但发送确认消息失败;这个就有问题了,因为用户A扣款成功了,但加钱业务没有订阅到确认消息,无法加钱。这里出现了数据不一致。
    那RocketMq是怎么解决的呢?- 状态回查

因为预备消息最终肯定会变为commit消息或Rollback消息,所以遍历预备消息去回查本地业务的执行状态,如果发现本地业务没有执行成功就rollBack,如果执行成功就发送commit消息。

@RocketMQTransactionListener(txProducerGroup = "tx-add-bonus-group")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class 
  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值