一:先说结果:
半消息其实也是事务消息,当我们想确保业务成功之后并且消息能够准确到达rocketmq的时候,
我们就可以用rocketmq提供的半消息机制。
总结就是: 业务成功了,消息也一定到了mq并且可消费。
二:直接发送mq消息会有什么问题?
场景1:业务先执行,然后再发送MQ。
try{
xxService.addCount(10); // 业务代码 用a表示,注意: 这段代码是用声明式事务包裹 //@Transaction
sendMessage(message); // mq发送消息代码 用b表示
....
}
问题: a成功,b失败,最终导致业务成功,发送消息失败了。
场景2:能不能不用使用编程事务来解决问题1?
try{
Transaction.setAutoCommit(false);
Transaction.begin();
xxService.addCount(10);
sendMessage(message);
Transaction.commit();
....
}
问题: 消息发过去了,但是事务没提交,如果message里面是你想传一个查询某条数据的id,
后面消费者根据这个id来查询你的数据,此时就可能查不到。
解决方案思考:采用分布式调度+事务表。
增加一个事务表,执行成功后,将需要发送的消息,存入表中,存完之后就可以发送消息了,发送MQ消息成功后,把消息状态给改了,如果MQ中间有任何失败。后期用定时任务去扫描事务表,发送MQ消息。
三:MQ的半消息原理简单分析
基于这个思路,那MQ半消息是怎么解决这个问题的呢?
如上图:
1:先告诉MQ我想发一个消息了,那么这个消息就会尝试到Broker。
2:MQ收到了。
3:行,那我处理我本地的业务了
4:处理完了,我告诉MQ,我处理完了,可以给消费者消费了
5:如果MQ迟迟没收到这条半消息的反馈,那么会定时的去调用生产者提供的checkLocalTransaction方法
6:此时业务方可以自行判断到底有没有处理业务完成。
7:根据业务方的自行判断,最终告诉MQ的消息处理结果。
四:总结
个人觉得,这个机制,跟自己设计的事务表+定时任务调度的方案是一样的,只不过在rocketmq
里面,它自己帮你实现了这一套,可以减少我们的工作量。但任何一个技术有好也有弊,还是
要根据自己的业务场景去考虑~~~
(以上所有内容纯属个人见解,如果有不准确或者更好的实现方案的还希望指出来,共同讨论~~~)