简介:
我们都知道目前流行的分布式事务有两大类分别是2pc和TCC。
1.2pc(两阶段提交)
假设a向数据库b写数据,a先尝试提交数据,b会把数据状态变成不可用
当a逻辑成功告诉b确认ok,b会修改数据状态变成可用,否则删除数据。
2.tcc(try confirm cancel)
假设a向数据库b写数据,b会尝试锁住这个数据,当a成功了调confirm方法,当a失败了掉cancel方法,confirm、cancel都由b实现。
rocketmq采用的是两阶段提交思想。
消息发送端开启事务,会先发送halfMessage,broker收到后会把它放入hf队列,然后保存到磁盘,并且给消息发送端一个消息确认。消息发送端收到确认,并且执行完本地所有逻辑后会commit,这样broker里的消息就变成可用的了。当然如果短时间内收不到commit或者rollback的话,broker在此期间会开一个定时任务,去检查hf队列里的消息,看事务是否成功,如果连不上消息发送端的话,默认一段时间后就会把该消息去除。
例子:
public class TransProducer {
public static void main(String[] args) throws Exception{
TransactionMQProducer producer = new TransactionMQProducer("xxogp");
//设置nameserver地址
producer.setNamesrvAddr("localhost:9876");
producer.setTransactionListener(new TransactionListener() {
//执行事务方法
public LocalTransactionState executeLocalTransaction(Message message, Object o) {
System.out.println("executeLocalTransaction=====");
System.out.println(new String(message.getBody()));
try {
int i = 10*10;
return LocalTransactionState.COMMIT_MESSAGE;
} catch (Exception e) {
return LocalTransactionState.ROLLBACK_MESSAGE;
}
}
//检查方法
//Broker端回调,检查事务
public LocalTransactionState checkLocalTransaction(MessageExt messageExt) {
System.out.println("checkLocalTransaction=====");
System.out.println(new String(messageExt.getBody()));
String flagMessage = "";
if("事务执行失败".equals(flagMessage)){
//将消息变成可用
return LocalTransactionState.ROLLBACK_MESSAGE;
}
if("事务执行成功".equals(flagMessage)){
//直接删除hf message
return LocalTransactionState.COMMIT_MESSAGE;
}
if("不知道是否成功".equals(flagMessage)){
//不知道情况过会再来检查
return LocalTransactionState.UNKNOW;
}
return LocalTransactionState.COMMIT_MESSAGE;
}
});
producer.start();
Message message = new Message("mytop111", "你好".getBytes());
TransactionSendResult send = producer.sendMessageInTransaction(message, null);
System.out.println("send = " + send);
}
}