作者回复: 考虑这样一种情况:订单创建成功了,还没来得及发消息,这个节点突然断电了。
作者回复: 这个总结非常到位,给你点赞!
作者回复: 非常好,完全正确!
作者回复: 如果本地事务提交失败,已经发出去的消息是无法撤回的,会导致数据不一致。
作者回复: indexFile的作用就是给commitlog做的索引,提升读取消息时的查询效率。
另外,关于事务的实现流程,总结的很到位,你还有哪些具体的问题不清楚,可以继续留言提出来。
作者回复: 其实是交全款,不发货。
作者回复: 👍👍👍
作者回复: 这种情况下是没有办法回滚的,也不应该回滚。
因为对于消息队列来说,它的一个重要功能就是解耦。
消费者的任何行为,不应该影响生产者。
对于你说的“坏消息”,反复消费都不能成功,有的MQ会把这种消息放到一个单独的特殊队列中,等着后续人工处理,避免卡死队列。
作者回复: 第一个问题,我们后面还有专门的一节课来讲事务是如何实现的,这里面会有你想要的答案。
第二第三个问题,RocketMQ给出的解决方案是,反查的结果返回的状态中,不仅有成功和失败,还有一个“不确定”的状态,意思就是“我现在不知道本地事务是不是成功了,将来它可能会成功,也可能会失败”,像你提的这两种情况,在实现反查接口的时候,都应该返回不确定的状态,RocketMQ在收到这个状态后,会定时多次进行反查,直到得到成功、失败的状态或者事务超时才结束。
作者回复: 到位。
作者回复: 是这样的。
作者回复: 如果有一个生产者和消费者都可以访问的,并且性能还不错数据库,肯定是使用这个数据库来实现事务比较好。
大部分事务消息使用的场景是,没有这样的数据库的。或者由于设计、安全或者网络原因,生产者消费者不能共享数据库,或者是数据库的性能达不到要求。
作者回复: 所以几乎所有的类似系统都会事先生成订单ID,而不是在插入数据库的时候才生成。
作者回复: 这个问题消息队列解决不了,可能需要用其他的分布式事务解决方案。
作者回复: 可以的。
作者回复: 支持的,但是每种MQ支持的“事务”都不太一样,使用前你需要看一下文档是不是你需要的那种“事务”
作者回复: 把数据库事务放到Kafka事务中的好处是,在发消息和执行SQL阶段,无论哪个操作失败了,都可以自动回滚。
只有“提交Kafka事务失败了”这个情况才需要手动处理。
而要是不用Kafka事务,先执行数据库事务,再发普通消息,如果发消息失败就要手动回滚数据库。
你要明白,提交事务只是设置一个状态,失败的概率要远远小于发消息的概率。
虽然理论上这两种情况失败都需手动处理,但是失败的概率差别很大,所以实际上还是非常有用的。
作者回复: 你可以看一下这个反查接口的定义,它检查的是本地事务(在我们这个例子里面就是数据库事务)有没有执行成功,并不比较数据是否一致。
作者回复: 坚持下来就是对老师最好的支持。