有内涵、有价值的文章第一时间送达!
BASE Transaction
Best efforts delivery transaction (已经实现).
Try confirm cancel transaction (待定).
Sharding-JDBC由于性能方面的考量,决定不支持强一致性分布式事务。
最大努力送达型事务
在分布式数据库的场景下,相信对于该数据库的操作最终一定可以成功,所以通过最大努力反复尝试送达操作。
最大努力送达型事务的架构图
最大努力送达型事务的架构图
摘自sharding-jdbc使用指南☞事务支持
执行过程有以下几种情况:
执行成功--如图所示,执行结果事件->监听执行事件->执行成功->清理事务日志
执行失败,同步重试成功--如图所示,执行结果事件->监听执行事件->执行失败->重试执行->执行成功->清理事务日志
执行失败,同步重试失败,异步重试成功--如图所示,执行结果事件->监听执行事件->执行失败->重试执行->执行失败->"异步送达作业"重试执行->执行成功->清理事务日志
执行失败,同步重试失败,异步重试失败,事务日志保留----如图所示,执行结果事件->监听执行事件->执行失败->重试执行->执行失败->"异步送达作业"重试执行->执行失败->... ...
说明:不管执行结果如何,执行前事件都会记录事务日志;执行事件类型包括3种:BEFOREEXECUTE,EXECUTEFAILURE和EXECUTESUCCESS;另外,这里的"同步"不是绝对的同步执行,而是通过google-guava的EventBus发布事件后,在监听端判断是EXECUTEFAILURE事件,最多重试 次;后面对 的源码分析有介绍;这里的"异步"通过外挂实现,在后面的文章10. sharding-jdbc源码之异步送达JOB会有分析;
适用场景
根据主键删除数据。
更新记录永久状态,如更新通知送达状态。
使用限制
使用最大努力送达型柔性事务的SQL需要满足幂等性。
INSERT语句要求必须包含主键,且不能是自增主键。
UPDATE语句要求幂等,不能是UPDATE xxx SET x=x+1
DELETE语句无要求。
开发示例
备注:SoftTransactionConfiguration支持的配置以及含义请参考sharding-jdbc使用指南☞事务支持,这段开发示例的代码也摘自这里;也可参考 模块中 如何使用柔性事务,但是这里的代码需要稍作修改,否则只是普通的执行逻辑,不是sharding-jdbc的执行逻辑:
核心源码分析
通过3. sharding-jdbc源码之路由&执行中对ExecutorEngine的分析可知,sharding-jdbc在执行SQL前后,分别调用 提交了事件,那么调用 的地方,就是柔性事务处理的地方,通过查看源码的调用关系可知,只有 调用了 ,所以柔性事务实现的核心在SoftTransactionManager这里;
柔性事务管理器
柔性事务实现在 中,核心源码如下:
从这段源码可知,柔性事务的几个重点如下,接下来一一根据源码进行分析;
事务日志存储器;
最大努力送达型事务监听器;
异步送达JOB任务;
1.事务日志存储器
柔性事务日志接口类为 ,有两个实现类:
RdbTransactionLogStorage:关系型数据库存储柔性事务日志;
MemoryTransactionLogStorage:内存存储柔性事务日志;
1.1.1事务日志核心接口
TransactionLogStorage中几个重要接口在两个实现类中的实现:
void add(TransactionLog):Rdb实现就是把事务日志TransactionLog 插入到表中,Memory实现就是把事务日志保存到中;
void remove(String id):Rdb实现就是从表中删除事务日志,Memory实现从中删除事务日志;
void increaseAsyncDeliveryTryTimes(String id):异步增加送达重试次数,即TransactionLog中的asyncDeliveryTryTimes+1;Rdb实现就是update表中字段加1;Memory实现就是TransactionLog中重新给asyncDeliveryTryTimes赋值;
findEligibleTransactionLogs(): 查询需要处理的事务日志,条件是:①,②,③,每次最多查询参数size条;Rdb实现通过sql从transaction_log表中查询,Memory实现遍历ConcurrentHashMap匹配符合条件的TransactionLog;
boolean processData():Rdb实现执行TransactionLog中的sql,如果执行过程中抛出异常,那么调用increaseAsyncDeliveryTryTimes()增加送达重试次数并抛出异常,如果执行成功,删除事务日志,并返回true;Memory实现直接返回false(因为processData()的目的是执行TransactionLog中的sql,而Memory类型无法触及数据库,所以返回false)
1.1.2事务日志存储核心源码
实现源码:
1.1.3事务日志存储样例
transaction_log中存储的事务日志样例:
1.2最大努力送达型事务监听器
核心源码如下:
BestEffortsDeliveryListener源码总结:
执行前,插入事务日志;
执行成功,则删除事务日志;
执行失败,则最大努力尝试次;
1.3 异步送达JOB任务
部署用于存储事务日志的数据库。
部署用于异步作业使用的zookeeper。
配置YAML文件,参照示例文件config.yaml。
下载并解压文件sharding-jdbc-transaction-async-job-$VERSION.tar,通过start.sh脚本启动异步作业。
异步送达JOB任务基于elastic-job,所以需要部署zookeeper;
END
领取专属 10元无门槛券
私享最新 技术干货