【发布时间】:2019-11-14 00:46:21
【问题描述】:
我有以下 rabbitMq 消费者:
Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, MQP.BasicProperties properties, byte[] body) throws IOException {
String message = new String(body, "UTF-8");
sendNotificationIntoTopic(message);
saveIntoDatabase(message);
}
};
可能会出现以下情况:
- 消息已成功发送到主题
- 与数据库的连接丢失,因此数据库插入失败。
因此我们的数据不一致。
预期结果要么两个动作都成功执行,要么都没有执行。
任何解决方案我该如何实现它?
附言
目前我有以下想法(请评论)
我们可以假设代理不会丢失任何消息。
我们必须订阅我们想要发送的主题。
- 将条目保存到数据库并设置字段
status值为“待定” - 尝试向主题发送数据。如果发送成功 - 更新字段
status值为“成功” -
我们必须有一个已调度的作业,它必须检查具有待处理状态的行。目前可能有两种情况:
3.1 根本没有发送通知
3.2 通知已发送但保存到数据库失败(概率很低但有可能)所以我们必须以某种方式区分这两种情况:我们可以将来自主题的消息存储在集合中,并且作业可以检查消息是否被接受。因此,如果作业找到与数据库行对应的消息,我们必须将状态更新为“成功”。否则我们必须从数据库中删除条目。
我认为我的想法有一些弱点(例如,如果我们有多节点应用程序,我们必须将消息存储在 hazelcast(或类似物)中,但这是假设失败的额外点)
【问题讨论】:
-
@user7294900 我们的重试次数有限。如果代理关闭,我们可以用尽所有尝试,并且我们再次遇到数据不一致
-
@user7294900 我不知道)但是我没有遇到过 10 亿次重试尝试的系统
-
解决方案是使用支持 JMS 和 XA 事务的消息系统,并使用 XA 事务管理器。或者拥有能够容忍不一致的业务逻辑。
-
@JB Nizet 当有人听到有关 XA 交易的消息时,他通常会变得紧张)
-
@JB Nizet 听起来很有趣,但我无法想象该怎么做
标签: java transactions rabbitmq messagebroker eventual-consistency