本文目录导读:

我将为您提供一个完整的Java分布式事务实现案例,包括多种主流方案。
项目结构
// 项目结构 distributed-transaction-demo/ ├── pom.xml ├── src/main/java/com/example/distributed/ │ ├── account/ │ │ ├── controller/ │ │ ├── service/ │ │ ├── mapper/ │ │ └── entity/ │ ├── order/ │ │ ├── controller/ │ │ ├── service/ │ │ ├── mapper/ │ │ └── entity/ │ ├── common/ │ │ ├── exception/ │ │ ├── response/ │ │ └── utils/ │ └── transaction/ │ ├── seata/ │ ├── mq/ │ └── tcc/
基于Seata的分布式事务实现
pom.xml依赖
<dependencies>
<!-- Spring Cloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- Seata -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
<!-- MyBatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<!-- MySQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
</dependencies>
application.yml配置
server:
port: 8081
spring:
application:
name: order-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
alibaba:
seata:
tx-service-group: my_test_tx_group
datasource:
url: jdbc:mysql://localhost:3306/order_db?useUnicode=true&characterEncoding=utf8
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
seata:
enabled: true
application-id: order-service
tx-service-group: my_test_tx_group
config:
type: nacos
nacos:
namespace: ""
serverAddr: localhost:8848
group: SEATA_GROUP
registry:
type: nacos
nacos:
application: seata-server
server-addr: localhost:8848
namespace: ""
group: SEATA_GROUP
订单服务实现
@Service
@Slf4j
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private AccountFeignClient accountFeignClient;
@Autowired
private ProductFeignClient productFeignClient;
@Override
@GlobalTransactional(name = "create-order", rollbackFor = Exception.class)
public Order createOrder(OrderDTO orderDTO) {
log.info("开始创建订单,订单数据:{}", orderDTO);
// 1. 扣减库存(调用商品服务)
boolean deductStock = productFeignClient.deductStock(
orderDTO.getProductId(), orderDTO.getQuantity());
if (!deductStock) {
throw new RuntimeException("库存不足");
}
// 2. 扣减余额(调用账户服务)
boolean deductBalance = accountFeignClient.deductBalance(
orderDTO.getUserId(), orderDTO.getAmount());
if (!deductBalance) {
throw new RuntimeException("余额不足");
}
// 3. 创建本地订单
Order order = new Order();
order.setOrderNo(generateOrderNo());
order.setUserId(orderDTO.getUserId());
order.setProductId(orderDTO.getProductId());
order.setQuantity(orderDTO.getQuantity());
order.setAmount(orderDTO.getAmount());
order.setStatus(1);
order.setCreateTime(new Date());
orderMapper.insert(order);
log.info("订单创建成功,订单号:{}", order.getOrderNo());
return order;
}
private String generateOrderNo() {
return "ORD" + System.currentTimeMillis() +
String.format("%04d", (int)(Math.random() * 10000));
}
}
账户服务实现
@Service
@Slf4j
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountMapper accountMapper;
@Override
@GlobalTransactional(name = "deduct-balance", rollbackFor = Exception.class)
public boolean deductBalance(Long userId, BigDecimal amount) {
log.info("开始扣减余额,用户:{},金额:{}", userId, amount);
// 查询用户账户
Account account = accountMapper.selectByUserId(userId);
if (account == null) {
throw new RuntimeException("用户不存在");
}
// 扣减余额
int result = accountMapper.deductBalance(userId, amount);
if (result == 0) {
throw new RuntimeException("余额不足");
}
// 记录交易流水
AccountTransaction transaction = new AccountTransaction();
transaction.setUserId(userId);
transaction.setAmount(amount.negate());
transaction.setType(1); // 1-支出
transaction.setCreateTime(new Date());
accountMapper.insertTransaction(transaction);
log.info("余额扣减成功,剩余余额:{}",
account.getBalance().subtract(amount));
return true;
}
}
基于消息队列的最终一致性方案
本地消息表方案
@Service
@Slf4j
public class MessageTransactionServiceImpl {
@Autowired
private MessageMapper messageMapper;
@Autowired
private RabbitTemplate rabbitTemplate;
@Transactional
public void createOrderAndMessage(OrderDTO orderDTO) {
// 1. 创建本地事务:插入订单和消息记录
Order order = new Order();
order.setOrderNo(generateOrderNo());
order.setUserId(orderDTO.getUserId());
order.setAmount(orderDTO.getAmount());
order.setStatus(1); // 待支付
orderMapper.insert(order);
// 2. 创建本地消息记录
TransactionMessage message = new TransactionMessage();
message.setMessageId(UUID.randomUUID().toString());
message.setOrderNo(order.getOrderNo());
message.setContent(JSONObject.toJSONString(orderDTO));
message.setStatus(0); // 0-待发送
message.setRetryCount(0);
message.setNextRetryTime(new Date());
messageMapper.insert(message);
log.info("订单和消息记录创建成功,订单号:{}", order.getOrderNo());
}
/**
* 定时任务:扫描并发送待处理消息
*/
@Scheduled(cron = "0/30 * * * * ?")
@Transactional
public void sendPendingMessages() {
// 查询待发送的消息(状态为0-待发送 且 超时5分钟)
List<TransactionMessage> pendingMessages =
messageMapper.selectPendingMessages(5, 10);
for (TransactionMessage message : pendingMessages) {
try {
// 发送消息到MQ
rabbitTemplate.convertAndSend(
"order.exchange",
"order.route",
message.getContent()
);
// 更新消息状态为已发送
messageMapper.updateStatus(message.getMessageId(), 1);
log.info("消息发送成功,消息ID:{}", message.getMessageId());
} catch (Exception e) {
log.error("消息发送失败,消息ID:{}", message.getMessageId(), e);
// 更新重试次数
messageMapper.updateRetryCount(message.getMessageId());
// 如果超过最大重试次数,标记为失败
if (message.getRetryCount() >= 5) {
messageMapper.updateStatus(message.getMessageId(), 3); // 3-失败
}
}
}
}
/**
* 消息补偿机制
*/
@Scheduled(cron = "0/60 * * * * ?")
public void compensateFailedMessages() {
// 查询处理补偿消息
List<TransactionMessage> compensateMessages =
messageMapper.selectCompensateMessages(30, 10);
for (TransactionMessage message : compensateMessages) {
// 查询订单状态
Order order = orderMapper.selectByOrderNo(message.getOrderNo());
// 如果订单已取消,则无需补偿
if (order != null && order.getStatus() == 0) {
continue;
}
// 重新发送消息
sendPendingMessages();
}
}
}
RabbitMQ可靠消息最终一致性
@Configuration
@Slf4j
public class RabbitMQTransactionConfig {
@Autowired
private ConnectionFactory connectionFactory;
@Bean
public RabbitTransactionManager rabbitTransactionManager() {
return new RabbitTransactionManager(connectionFactory);
}
/**
* 消息发送服务
*/
@Service
public static class MessageSender {
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private CorrelationDataService correlationDataService;
/**
* 发送可靠消息
*/
@Transactional
public void sendReliableMessage(ReliableMessage message) {
// 1. 保存消息到本地
correlationDataService.saveMessage(message);
// 2. 发送消息
CorrelationData correlationData = new CorrelationData(message.getMessageId());
rabbitTemplate.convertAndSend(
"exchange",
"routingKey",
message,
correlationData
);
}
/**
* 发送延迟消息(用于延迟检查)
*/
public void sendDelayMessage(String messageId, long delayTime) {
log.info("发送延迟检查消息,消息ID:{}", messageId);
MessageProperties properties = new MessageProperties();
properties.setDelay(Math.toIntExact(delayTime));
Message message = MessageBuilder.builder()
.setBody(messageId.getBytes())
.andProperties(properties)
.build();
rabbitTemplate.convertAndSend(
"delay.exchange",
"delay.route",
message
);
}
}
/**
* 消费者确认服务
*/
@Service
public static class MessageConsumer {
@Autowired
private CorrelationDataService correlationDataService;
@RabbitListener(queues = "order.queue")
public void consumeOrder(Message message, Channel channel) throws Exception {
String messageId = new String(message.getBody());
log.info("消费者收到消息ID:{}", messageId);
try {
// 1. 幂等性检查
if (correlationDataService.isDuplicate(messageId)) {
log.warn("重复消息,消息ID:{}", messageId);
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
return;
}
// 2. 处理业务逻辑
ReliableMessage reliableMessage =
correlationDataService.getMessage(messageId);
processBusiness(reliableMessage);
// 3. 标记消息为已完成
correlationDataService.markSuccess(messageId);
// 4. 确认消息
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
} catch (Exception e) {
log.error("消息处理失败,消息ID:{}", messageId, e);
// 重试或放入死信队列
if (message.getMessageProperties().getRedelivered()) {
channel.basicReject(
message.getMessageProperties().getDeliveryTag(), false);
} else {
channel.basicNack(
message.getMessageProperties().getDeliveryTag(), false, true);
}
}
}
private void processBusiness(ReliableMessage message) {
// 处理具体业务
log.info("处理业务逻辑:{}", message.getBusinessType());
}
}
}
TCC分布式事务实现
TCC通用接口
public interface TccService {
/**
* Try阶段
*/
boolean tryMethod(TccContext context);
/**
* Confirm阶段
*/
boolean confirmMethod(TccContext context);
/**
* Cancel阶段
*/
boolean cancelMethod(TccContext context);
}
TCC事务管理器
@Component
@Slf4j
public class TccTransactionManager {
@Autowired
private TccTransactionDao transactionDao;
private ThreadLocal<TccTransaction> currentTransaction = new ThreadLocal<>();
/**
* 开启事务
*/
@Transactional
public TccTransaction beginTransaction(String businessType) {
TccTransaction transaction = new TccTransaction();
transaction.setTxId(UUID.randomUUID().toString());
transaction.setBusinessType(businessType);
transaction.setStatus(0); // 0-进行中
transaction.setCreateTime(new Date());
currentTransaction.set(transaction);
transactionDao.insert(transaction);
log.info("开启TCC事务,事务ID:{}", transaction.getTxId());
return transaction;
}
/**
* 注册参与者
*/
public void registerParticipant(TccService service, TccContext context) {
TccTransaction transaction = currentTransaction.get();
if (transaction == null) {
throw new RuntimeException("无活动事务");
}
TccParticipant participant = new TccParticipant();
participant.setTxId(transaction.getTxId());
participant.setServiceName(service.getClass().getName());
participant.setTryMethod(service);
participant.setContext(context);
participant.setStatus(0);
// 保存参与者信息
transactionDao.insertParticipant(participant);
}
/**
* 提交事务
*/
@Transactional
public void commit() {
TccTransaction transaction = currentTransaction.get();
if (transaction == null) {
throw new RuntimeException("无活动事务");
}
// 1. 执行所有参与者的Confirm阶段
List<TccParticipant> participants =
transactionDao.selectParticipants(transaction.getTxId());
for (TccParticipant participant : participants) {
try {
boolean success = participant.getTryMethod()
.confirmMethod(participant.getContext());
if (success) {
participant.setStatus(2);
transactionDao.updateParticipant(participant);
} else {
throw new RuntimeException("Confirm阶段失败");
}
} catch (Exception e) {
log.error("Confirm阶段执行失败", e);
// 抛出异常,触发Cancel
throw e;
}
}
// 2. 更新事务状态为已提交
transaction.setStatus(1);
transactionDao.update(transaction);
// 3. 清理ThreadLocal
currentTransaction.remove();
log.info("TCC事务提交成功,事务ID:{}", transaction.getTxId());
}
/**
* 回滚事务
*/
@Transactional
public void rollback() {
TccTransaction transaction = currentTransaction.get();
if (transaction == null) {
return;
}
// 1. 执行所有参与者的Cancel阶段
List<TccParticipant> participants =
transactionDao.selectParticipants(transaction.getTxId());
for (TccParticipant participant : participants) {
try {
participant.getTryMethod()
.cancelMethod(participant.getContext());
participant.setStatus(3);
transactionDao.updateParticipant(participant);
} catch (Exception e) {
log.error("Cancel阶段执行失败", e);
// 记录失败,进行重试
}
}
// 2. 更新事务状态为已回滚
transaction.setStatus(4);
transactionDao.update(transaction);
// 3. 清理ThreadLocal
currentTransaction.remove();
log.info("TCC事务已回滚,事务ID:{}", transaction.getTxId());
}
}
具体业务TCC实现
@Service
@Slf4j
public class AccountTccService implements TccService {
@Autowired
private AccountMapper accountMapper;
@Autowired
private FrozenAccountMapper frozenAccountMapper;
@Override
@Transactional
public boolean tryMethod(TccContext context) {
log.info("执行Try阶段,上下文:{}", context);
// 解析业务参数
TccAccountContext accountContext = JSONObject.parseObject(
context.getBusinessContext(), TccAccountContext.class);
// 1. 检查余额是否充足
Account account = accountMapper.selectForUpdate(
accountContext.getUserId());
if (account.getBalance().compareTo(accountContext.getAmount()) < 0) {
return false;
}
// 2. 冻结余额
int result = accountMapper.freezeBalance(
accountContext.getUserId(),
accountContext.getAmount()
);
if (result == 0) {
return false;
}
// 3. 记录冻结记录
FrozenAccount frozenAccount = new FrozenAccount();
frozenAccount.setUserId(accountContext.getUserId());
frozenAccount.setAmount(accountContext.getAmount());
frozenAccount.setTxId(context.getTxId());
frozenAccount.setStatus(1); // 1-冻结中
frozenAccount.setCreateTime(new Date());
frozenAccountMapper.insert(frozenAccount);
log.info("余额冻结成功,用户:{},金额:{}",
accountContext.getUserId(), accountContext.getAmount());
return true;
}
@Override
@Transactional
public boolean confirmMethod(TccContext context) {
log.info("执行Confirm阶段,事务ID:{}", context.getTxId());
// 解析业务参数
TccAccountContext accountContext = JSONObject.parseObject(
context.getBusinessContext(), TccAccountContext.class);
// 1. 转账:从冻结余额中扣减
int result = accountMapper.completeFrozenTransaction(
accountContext.getUserId(),
accountContext.getAmount(),
accountContext.getTargetUserId()
);
if (result > 0) {
// 2. 更新冻结记录状态
frozenAccountMapper.updateStatus(
context.getTxId(), 2); // 2-已完成
log.info("转账确认成功,事务ID:{}", context.getTxId());
return true;
}
return false;
}
@Override
@Transactional
public boolean cancelMethod(TccContext context) {
log.info("执行Cancel阶段,事务ID:{}", context.getTxId());
// 解析业务参数
TccAccountContext accountContext = JSONObject.parseObject(
context.getBusinessContext(), TccAccountContext.class);
// 1. 解冻余额
int result = accountMapper.unfreezeBalance(
accountContext.getUserId(),
accountContext.getAmount()
);
if (result > 0) {
// 2. 更新冻结记录状态
frozenAccountMapper.updateStatus(
context.getTxId(), 3); // 3-已取消
log.info("转账取消成功,事务ID:{}", context.getTxId());
return true;
}
return false;
}
}
XA分布式事务实现
@Configuration
@Slf4j
public class XaTransactionConfig {
/**
* 配置XA数据源
*/
@Bean("orderDataSource")
public DataSource orderDataSource() {
MysqlXADataSource xaDataSource = new MysqlXADataSource();
xaDataSource.setUrl("jdbc:mysql://localhost:3306/order_db");
xaDataSource.setUser("root");
xaDataSource.setPassword("root");
return new AtomikosDataSourceBean() {
{
setUniqueResourceName("orderDataSource");
setXaDataSource(xaDataSource);
setMinPoolSize(5);
setMaxPoolSize(20);
setMaxLifetime(30000);
setBorrowConnectionTimeout(10);
}
};
}
@Bean("accountDataSource")
public DataSource accountDataSource() {
MysqlXADataSource xaDataSource = new MysqlXADataSource();
xaDataSource.setUrl("jdbc:mysql://localhost:3306/account_db");
xaDataSource.setUser("root");
xaDataSource.setPassword("root");
return new AtomikosDataSourceBean() {
{
setUniqueResourceName("accountDataSource");
setXaDataSource(xaDataSource);
setMinPoolSize(5);
setMaxPoolSize(20);
setMaxLifetime(30000);
setBorrowConnectionTimeout(10);
}
};
}
/**
* 配置JTA事务管理器
*/
@Bean(name = "atomikosTransactionManager")
public JtaTransactionManager jtaTransactionManager() {
return new JtaTransactionManager(
new UserTransactionAdapter(),
new TransactionManagerImp()
);
}
/**
* 使用全局事务
*/
@Service
public static class XaOrderService {
@Autowired
@Qualifier("orderDataSource")
private DataSource orderDataSource;
@Autowired
@Qualifier("accountDataSource")
private DataSource accountDataSource;
@Autowired
private PlatformTransactionManager transactionManager;
/**
* 跨库事务操作
*/
public void createOrderAcrossDatabases(OrderDTO orderDTO) {
TransactionTemplate transactionTemplate =
new TransactionTemplate(transactionManager);
transactionTemplate.execute(status -> {
try {
// 1. 订单库操作
JdbcTemplate orderJdbc = new JdbcTemplate(orderDataSource);
String orderSql = "INSERT INTO orders (order_no, user_id, amount) VALUES (?, ?, ?)";
orderJdbc.update(orderSql,
generateOrderNo(),
orderDTO.getUserId(),
orderDTO.getAmount()
);
// 2. 账户库操作
JdbcTemplate accountJdbc = new JdbcTemplate(accountDataSource);
String accountSql = "UPDATE accounts SET balance = balance - ? WHERE user_id = ?";
int rows = accountJdbc.update(accountSql,
orderDTO.getAmount(),
orderDTO.getUserId()
);
if (rows == 0) {
throw new RuntimeException("账户扣款失败");
}
return true;
} catch (Exception e) {
// 抛出异常会自动回滚所有事务
throw e;
}
});
}
}
}
事务补偿框架
@Component
@Slf4j
public class TransactionCompensator {
@Autowired
private CompensateRecordDao compensateRecordDao;
@Autowired
private RetryTemplate retryTemplate;
/**
* 执行带补偿的事务操作
*/
public <T> T executeWithCompensation(
String businessType,
TransactionCallback<T> mainAction,
TransactionCallback<T> compensateAction) {
// 创建补偿记录
String transactionId = UUID.randomUUID().toString();
CompensateRecord record = new CompensateRecord();
record.setTransactionId(transactionId);
record.setBusinessType(businessType);
record.setStatus(0); // 0-处理中
record.setCreateTime(new Date());
compensateRecordDao.insert(record);
try {
// 执行主事务
T result = mainAction.doInTransaction();
// 更新记录为成功
compensateRecordDao.updateStatus(transactionId, 1);
log.info("事务执行成功,事务ID:{}", transactionId);
return result;
} catch (Exception e) {
log.error("事务执行失败,开始补偿,事务ID:{}", transactionId, e);
// 执行补偿事务
try {
retryTemplate.execute(context -> {
compensateAction.doInTransaction();
return null;
});
// 更新记录为已补偿
compensateRecordDao.updateStatus(transactionId, 2);
log.info("补偿成功,事务ID:{}", transactionId);
} catch (Exception retryException) {
// 补偿失败,记录并加入死信队列
compensateRecordDao.updateStatus(transactionId, 3);
addToDeadLetterQueue(record);
log.error("补偿失败,加入死信队列,事务ID:{}", transactionId, retryException);
}
throw e;
}
}
/**
* 死信队列处理(后台任务)
*/
@Scheduled(cron = "0 */5 * * * ?")
public void processDeadLetterQueue() {
List<CompensateRecord> deadLetters =
compensateRecordDao.selectStatus(3, 10);
for (CompensateRecord record : deadLetters) {
log.info("处理死信队列中的补偿记录,事务ID:{}", record.getTransactionId());
// 根据类型进行人工处理或自动处理
handleDeadLetter(record);
}
}
@FunctionalInterface
public interface TransactionCallback<T> {
T doInTransaction();
}
}
测试用例
@SpringBootTest
@RunWith(SpringRunner.class)
public class DistributedTransactionTest {
@Autowired
private OrderServiceImpl orderService;
@Autowired
private MessageTransactionServiceImpl messageTransactionService;
@Autowired
private TccTransactionManager tccTransactionManager;
@Autowired
private AccountTccService accountTccService;
/**
* 测试Seata分布式事务
*/
@Test
public void testSeataTransaction() {
// 创建订单
OrderDTO orderDTO = new OrderDTO();
orderDTO.setUserId(1L);
orderDTO.setProductId(100L);
orderDTO.setQuantity(2);
orderDTO.setAmount(new BigDecimal("100.00"));
try {
Order order = orderService.createOrder(orderDTO);
Assert.assertNotNull(order);
Assert.assertEquals("ORD", order.getOrderNo().substring(0, 3));
log.info("Seata分布式事务测试成功,订单号:{}", order.getOrderNo());
} catch (Exception e) {
log.error("Seata分布式事务测试失败", e);
Assert.fail(e.getMessage());
}
}
/**
* 测试本地消息表方案
*/
@Test
public void testLocalMessageTable() {
OrderDTO orderDTO = new OrderDTO();
orderDTO.setUserId(2L);
orderDTO.setProductId(200L);
orderDTO.setQuantity(1);
orderDTO.setAmount(new BigDecimal("50.00"));
try {
messageTransactionService.createOrderAndMessage(orderDTO);
log.info("本地消息表方案测试成功");
// 等待定时任务执行
Thread.sleep(10000);
// 验证消息发送状态
List<TransactionMessage> messages = messageTransactionService
.queryMessagesByOrderNo(orderDTO.getOrderNo());
Assert.assertNotNull(messages);
Assert.assertEquals(1, messages.size());
} catch (Exception e) {
log.error("本地消息表方案测试失败", e);
Assert.fail(e.getMessage());
}
}
/**
* 测试TCC事务
*/
@Test
public void testTccTransaction() {
// 模拟转账:从用户1转到用户2
TccAccountContext context = new TccAccountContext();
context.setUserId(1L);
context.setTargetUserId(2L);
context.setAmount(new BigDecimal("100.00"));
TccContext tccContext = new TccContext();
tccContext.setTxId(UUID.randomUUID().toString());
tccContext.setBusinessContext(JSONObject.toJSONString(context));
try {
// 1. 开启事务
tccTransactionManager.beginTransaction("transfer");
// 2. 注册参与者(转账服务)
tccTransactionManager.registerParticipant(accountTccService, tccContext);
// 3. 执行业务逻辑
boolean tryResult = accountTccService.tryMethod(tccContext);
if (!tryResult) {
// 提交失败,回滚
tccTransactionManager.rollback();
Assert.fail("TCC Try阶段失败");
}
// 4. 提交事务
tccTransactionManager.commit();
log.info("TCC事务测试成功");
} catch (Exception e) {
log.error("TCC事务测试失败", e);
// 回滚
tccTransactionManager.rollback();
Assert.fail(e.getMessage());
}
}
/**
* 测试XA事务
*/
@Test
public void testXaTransaction() {
XaOrderService xaOrderService = new XaOrderService();
try {
OrderDTO orderDTO = new OrderDTO();
orderDTO.setUserId(3L);
orderDTO.setAmount(new BigDecimal("200.00"));
xaOrderService.createOrderAcrossDatabases(orderDTO);
log.info("XA事务测试成功");
} catch (Exception e) {
log.error("XA事务测试失败", e);
Assert.fail(e.getMessage());
}
}
}
这个分布式事务实现涵盖了以下几种经典方案:
Seata AT模式
- 适合中小型项目
- 自动回滚,代码侵入小
- 适合读多写少的场景
本地消息表方案
- 最终一致性
- 实现简单,可靠性高
- 适合跨系统异步调用
TCC模式
- 需要实现Try/Confirm/Cancel三个接口
- 控制粒度细,灵活性强
- 适合资金相关的高一致性场景
XA协议
- 强一致性
- 性能开销较大
- 适合对一致性要求极高的场景
消息队列最终一致性
- 通过消息中间件解耦
- 异步处理,性能好
- 适合高并发的电商场景
选择建议:
- 要求强一致性,且业务简单:使用Seata AT模式
- 资金类业务:使用TCC模式
- 跨系统,容忍最终一致:使用消息队列方案
- 数据一致性要求极高:使用XA协议
需要我详细展开某个方案的实现吗?
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播