16 年的时候,基于 RocketMQ 早期的版本,写了 《RocketMQ 源码分析 —— 事务消息》 文章,虽然 RocketMQ版本不太一样,但是大体的思路是差不多的,可以帮助胖友更容易的读懂事务消息相关的源码。
简单看了下最新版本的 RocketMQ 的事务代码,新增了RMQ_SYS_TRANS_HALF_TOPIC和RMQ_SYS_TRANS_OP_HALF_TOPIC两个队列。Producer 发送 PREPARED Message 到 Broker 后,先存储到 RMQ_SYS_TRANS_HALF_TOPIC 队列中。Producer 提交或回滚 PREPARED Message 时,会添加一条消息到 RMQ_SYS_TRANS_OP_HALF_TOPIC队列中,标记这个消息已经处理。
Producer 提交 PREPARED Message 时,会将当前消息存储到原 Topic 的队列中,从而该消息能够被Consumer 拉取消费。
如何实现 RocketMQ 高可用?
在 「RocketMQ 由哪些角色组成?」 中,我们看到 RocketMQ 有四个角色,需要考虑每个角色的高可用。
?? 1. Producer
1、Producer 自身在应用中,所以无需考虑高可用。
2、Producer 配置多个 Namesrv 列表,从而保证 Producer 和 Namesrv 的连接高可用。并且,会从Namesrv 定时拉取最新的 Topic 信息。
3、Producer 会和所有 Consumer 直连,在发送消息时,会选择一个 Broker 进行发送。如果发送失败,则会使用另外一个 Broker 。
4、Producer 会定时向 Broker 心跳,证明其存活。而 Broker 会定时检测,判断是否有 Producer 异常下线。?? 2. Consumer
1、Consumer 需要部署多个节点,以保证 Consumer 自身的高可用。当相同消费者分组中有新的Consumer 上线,或者老的 Consumer 下线,会重新分配 Topic 的 Queue 到目前消费分组的 Consumer们。
2、Consumer 配置多个 Namesrv 列表,从而保证 Consumer 和 Namesrv 的连接高可用。并且,会从Consumer 定时拉取最新的 Topic 信息。
3、Consumer 会和所有 Consumer 直连,消费相应分配到的 Queue 的消息。如果消费失败,则会发回消息到 Broker 中。
4、Consumer 会定时向 Broker 心跳,证明其存活。而 Broker 会定时检测,判断是否有 Consumer 异常下线。?? 3. Namesrv
1、Namesrv 需要部署多个节点,以保证 Namesrv 的高可用。
2、Namesrv 本身是无状态,不产生数据的存储,是通过 Broker 心跳将 Topic 信息同步到 Namesrv 中。3、多个 Namesrv 之间不会有数据的同步,是通过 Broker 向多个 Namesrv 多写。?? 4. Broker
1、多个 Broker 可以形成一个 Broker 分组。每个 Broker 分组存在一个 Master 和多个 Slave 节点。
Master 节点,可提供读和写功能。Slave 节点,可提供读功能。
Master 节点会不断发送新的 CommitLog 给 Slave节点。Slave 节点不断上报本地的 CommitLog 已经同步到的位置给 Master 节点。
Slave 节点会从 Master 节点拉取消费进度、Topic 配置等等。2、多个 Broker 分组,形成 Broker 集群。
Broker 集群和集群之间,不存在通信与数据同步。
3、Broker 可以配置同步刷盘或异步刷盘,根据消息的持久化的可靠性来配置。?? 总结
目前官方提供三套配置:
2m-2s-asyncbrokerClusterNameDefaultClusterDefaultClusterDefaultClusterDefaultCluster2m-2s-syncbrokerClusterNameDefaultClusterDefaultClusterDefaultClusterDefaultCluster2m-noslave
brokerNamebroker-abroker-abroker-bbroker-b
brokerRoleSYNC_MASTERSLAVESYNC_MASTERSLAVE
brokerId0101
brokerNamebroker-abroker-abroker-bbroker-b
brokerRoleASYNC_MASTERSLAVE
ASYNC_MASTERSLAVE
brokerId0101
brokerClusterNameDefaultClusterDefaultClusterbrokerNamebroker-abroker-bbrokerRoleASYNC_MASTERASYNC_MASTERbrokerId00相关的源码解析,胖友可以看看 《RocketMQ 源码分析 —— 高可用》 。如何保证消费者的消费消息的幂等性?在 《精尽【消息队列 】面试题》 中,已经解析过该问题。当然,我们有几点要补充下:Producer 在发送消息时,默认会生成消息编号( msgId ),可见org.apache.rocketmq.common.message.MessageClientExt 类。 Broker 在存储消息时,会生成结合 o?set 的消息编号( offsetMsgId ) 。Consumer 在消费消息失败后,将该消息发回 Broker 后,会产生新的 offsetMsgId 编号,但是 msgId不变。重点补充说明RocketMQ 涉及的内容很多,能够问的问题也特别多,但是我们不能仅仅为了面试,应该是为了对 RocketMQ 了解更多,使用的更优雅。所以,强烈胖友认真撸下如下三个 PDF :《RocketMQ 用户指南》 基于 RocketMQ 3 的版本。《RocketMQ 原理简介》 基于 RocketMQ 3 的版本。《RocketMQ 最佳实践》 基于 RocketMQ 3 的版本。 666. 彩蛋RocketMQ 能够问的东西,真的挺多的,中间也和一些朋友探讨过。如果胖友有什么想要问的,可以在星球给留言。参考与推荐如下文章:javahongxi 《RocketMQ 架构模块解析》薛定谔的风口猪 《RocketMQ —— 角色与术语详解》阿里中间件小哥 《一文讲透 Apache RocketMQ 技术精华》