阿飞Javaer,转载请注明原创出处,谢谢!
BASE Transaction
- Best efforts delivery transaction (已经实现).
- Try confirm cancel transaction (待定).
Sharding-JDBC由于性能方面的考量,决定不支持强一致性分布式事务。
最大努力送达型事务
在分布式数据库的场景下,相信对于该数据库的操作最终一定可以成功,所以通过最大努力反复尝试送达操作。
最大努力送达型事务的架构图
执行过程有以下几种情况:
1. 执行成功–如图所示,执行结果事件->监听执行事件->执行成功->清理事务日志
2. 执行失败,同步重试成功–如图所示,执行结果事件->监听执行事件->执行失败->重试执行->执行成功->清理事务日志
3. 执行失败,同步重试失败,异步重试成功–如图所示,执行结果事件->监听执行事件->执行失败->重试执行->执行失败->”异步送达作业”重试执行->执行成功->清理事务日志
4. 执行失败,同步重试失败,异步重试失败,事务日志保留—-如图所示,执行结果事件->监听执行事件->执行失败->重试执行->执行失败->”异步送达作业”重试执行->执行失败->… …
说明:不管执行结果如何,执行前事件都会记录事务日志;执行事件类型包括3种:BEFORE_EXECUTE,EXECUTE_FAILURE和EXECUTE_SUCCESS;另外,这里的”同步“不是绝对的同步执行,而是通过google-guava的EventBus发布事件后,在监听端判断是EXECUTE_FAILURE事件,最多重试
syncMaxDeliveryTryTimes
次;后面对BestEffortsDeliveryListener
的源码分析有介绍;这里的”异步“通过外挂实现,在后面的文章10. sharding-jdbc源码之异步送达JOB会有分析;
适用场景
- 根据主键删除数据。
- 更新记录永久状态,如更新通知送达状态。
使用限制
- 使用最大努力送达型柔性事务的SQL需要满足幂等性。
- INSERT语句要求必须包含主键,且不能是自增主键。
- UPDATE语句要求幂等,不能是UPDATE xxx SET x=x+1
- DELETE语句无要求。
开发示例
// 1. 配置SoftTransactionConfiguration
SoftTransactionConfiguration transactionConfig = new SoftTransactionConfiguration(dataSource);
// 配置相关请看后面的备注
transactionConfig.setXXX();
// 2. 初始化SoftTransactionManager
SoftTransactionManager transactionManager = new SoftTransactionManager(transactionConfig);
transactionManager.init();
// 3. 获取BEDSoftTransaction
BEDSoftTransaction transaction = (BEDSoftTransaction) transactionManager.getTransaction(SoftTransactionType.BestEffortsDelivery);
// 4. 开启事务
transaction.begin(connection);
// 5. 执行JDBC
/*
code here
*/
*
// 6.关闭事务
transaction.end();
备注:SoftTransactionConfiguration支持的配置以及含义请参考sharding-jdbc使用指南☞事务支持,这段开发示例的代码也摘自这里;也可参考
sharding-jdbc-transaction
模块中com.dangdang.ddframe.rdb.transaction.soft.integrate.SoftTransactionTest
如何使用柔性事务,但是这里的代码需要稍作修改,否则只是普通的执行逻辑,不是sharding-jdbc的执行逻辑:
@Test
public void bedSoftTransactionTest() throws SQLException {
SoftTransactionManager transactionManagerFactory = new SoftTransactionManager(getSoftTransactionConfiguration(getShardingDataSource()));
// 初始化柔性事务管理器
transactionManagerFactory.init();
BEDSoftTransaction transactionManager = (BEDSoftTransaction) transactionManagerFactory.getTransaction(SoftTransactionType.BestEffortsDelivery);
transactionManager.begin(getShardingDataSource().getConnection());
// 执行INSERT SQL(DML类型),如果执行过程中异常,会在`BestEffortsDeliveryListener`中重试
insert();
transactionManager.end();
}
private void insert() {
String dbSchema = "insert into transaction_test(id, remark) values (2, ?)";
try (
// 将.getConnection("db_trans", SQLType.DML)移除,这样的话,得到的才是ShardingConnection
Connection conn = getShardingDataSource().getConnection();
PreparedStatement preparedStatement = conn.prepareStatement(dbSchema)) {
preparedStatement.setString(1