三,事务消息
RocketMQ提供类似X/Open XA的分布式事务功能来确保业务发送方和MQ消息的最终一致性,其本质是通过半消息的方式把分布式事务放在MQ端来处理。
原理图
其中:
1,发送方向消息队列 RocketMQ 服务端发送消息。
2,服务端将消息持久化成功之后,向发送方 ACK 确认消息已经发送成功,此时消息为半消息。
3,发送方开始执行本地事务逻辑。
4,发送方根据本地事务执行结果向服务端提交二次确认(Commit 或是 Rollback),服务端收到 Commit 状态则将半消息标记为可投递,订阅方最终将收到该消息;服务端收到 Rollback 状态则删除半消息,订阅方将不会接受该消息。
5,在断网或者是应用重启的特殊情况下,上述步骤 4 提交的二次确认最终未到达服务端,经过固定时间后服务端将对该消息发起消息回查。
6,发送方收到消息回查后,需要检查对应消息的本地事务执行的最终结果。
7,发送方根据检查得到的本地事务的最终状态再次提交二次确认,服务端仍按照步骤 4 对半消息进行操作。
RocketMQ的半消息机制的注意事项是
1,根据第六步可以看出他要求发送方提供业务回查接口。
2,不能保证发送方的消息幂等,在ack没有返回的情况下,可能存在重复消息
3,消费方要做幂等处理。
核心代码
final BusinessService businessService = new BusinessService(); // 本地业务
具体代码参考文档:https://help.aliyun.com/document_detail/29548.html?spm=a2c4g.11186623.6.570.5d5738a49FJl1t[2]
所有消息发布原理图
producer完全无状态,可以集群部署。
Name Server集群:
NameServer是一个几乎无状态的节点,可集群部署,节点之间无任何信息同步,NameServer很像注册中心的功能。
听说阿里之前的NameServer 是用ZooKeeper做的,可能因为Zookeeper不能满足大规模并发的要求,所以之后NameServer 是阿里自研的。
NameServer其实就是一个路由表,他管理Producer和Comsumer之间的发现和注册。
Broker集群:
Broker部署相对复杂,Broker分为Master与Slave,一个Master可以对应多个Slaver,但是一个Slaver只能对应一个Master,Master与Slaver的对应关系通过指定相同的BrokerName。
不同的BrokerId来定义,BrokerId为0表示Master,非0表示Slaver。Master可以部署多个。每个Broker与NameServer集群中的所有节点建立长连接,定时注册Topic信息到所有的NameServer。
Consumer集群:
订阅方式
消息队列 RocketMQ 支持以下两种订阅方式:
集群订阅:同一个 Group ID 所标识的所有 Consumer 平均分摊消费消息。 例如某个 Topic 有 9 条消息,一个 Group ID 有 3 个 Consumer 实例,那么在集群消费模式下每个实例平均分摊,只消费其中的 3 条消息。
广播订阅:同一个 Group ID 所标识的所有 Consumer 都会各自消费某条消息一次。 例如某个 Topic 有 9 条消息,一个 Group ID 有 3 个 Consumer 实例,那么在广播消费模式下每个实例都会各自消费 9 条消息。
OADCASTING);
订阅消息关键代码:
注意事项:
消费端要做幂等处理,所有MQ基本上都不会做幂等处理,需要业务端处理,原因是如果在MQ端做幂等处理会带来MQ的复杂度,而且严重影响MQ的性能。
消息收发模型
主子账号创建
创建主子账号的原因是权限问题。下面是主账号创建流程图
详细操作地址:https://help.aliyun.com/document_detail/34411.html?spm=a2c4g.11186623.6.555.38c57f91JXUK7o[3]
子账号流程图详细操作地址:https://help.aliyun.com/document_detail/96402.html?spm=a2c4g.11186623.6.556.60194fedfSkxIB[4]
三、MQ是微服务架构
非常重要的部分
MQ的诞生把原来的同步架构思维转变到异步架构思维提供一种方法,为大规模,高并发的业务场景的稳定性实现提供了很好的解决思路。
Martin Fowler强调:分布式调用的第一原则就是不要分布式。这句话看似颇具哲理,然而就企业应用系统而言,只要整个系统在不停地演化,并有多个子系统共同存在时,这条原则就会被迫打破。
Martin Fowler提出的这条原则,一方面是希望设计者能够审慎地对待分布式调用,另一方面却也是分布式系统自身存在的缺陷所致。
所以微服务并不是万能药,适合的架构才是最好的架构。