Stream Load的事务管理由FE负责,Doris的事务状态包括:PREPARE、COMMITTED、VISIBLE和ABORTED。
数据导入开始之前,Coordinator BE节点会向FE发送Begin Transaction请求,FE会为当前label开启一个新的事务,并为事务分配Transaction Id,同时将事务状态设置为PREPARE,然后将Transaction Id以及Begin Transaction成功的信息返回给Coordinator BE。
当数据在所有Executor BE节点完成写入之后,Coordinator BE节点会向FE发送Commit Transaction请求,FE会判断每一个Tablet成功写入数据的副本数量是否超过了Tablet副本总数的一半,如果每一个Tablet成功写入数据的副本数量都超过Tablet副本总数的一半(多数成功),则Commit Transaction成功,并将事务状态设置为COMMITTED;否则,向Coordinator BE返回Commit Transaction失败的信息。COMMITTED状态表示数据已经成功写入,但是数据还不可见,需要继续执行Publish Version任务,此后,事务不可被回滚。
当从FE获取导入计划失败、执行数据导入失败或Commit Transaction失败时,Coordinator BE节点会向FE发送Rollback Transaction请求,执行事务回滚。FE收到事务回滚的请求之后,会将事务的状态设置为ABORTED,并通过Thrift RPC向Executor BE发送Clear Transaction的请求,Clear Transaction任务在BE节点异步执行,将数据导入生成的Rowset标记为不可用,这些Rowset在之后会从BE上被删除。状态为COMMITTED的事务(Commit Transaction成功但Publish Version超时的事务)不能被回滚。
FE会有一个单独的线程对Commit成功的Transaction执行Publish Version,FE执行Publish Version时会通过Thrift RPC向Transaction相关的所有Executor BE节点下发Publish Version请求,Publish Version任务在各个Executor BE节点异步执行,将数据导入生成的Rowset变为可见的数据版本。当Executor BE上所有的Publish Version任务执行成功,FE会将事务状态设置为VISIBLE,并向Coordinator BE返回Commit Transaction以及Publish Version成功的信息。如果存在某些Publish Version任务失败,FE会向Executor BE节点重复下发Publish Version请求直到之前失败的Publish Version任务成功。如果在一定超时时间之后,事务状态还没有被设置为VISIBLE,FE就会向Coordinator BE返回Commit Transaction成功但Publish Version超时的信息(注意,此时数据依然是写入成功的,只是还处于不可见状态,用户需要使用额外的命令查看并等待事务状态最终变为VISIBLE。)
TCC 指的是Try - Confirm - Cancel。Try 指的是预留,即资源的预留和锁定。Confirm 指的是确认操作,这一步其实就是真正的执行了。Cancel 指的是撤销操作,可以理解为把预留阶段的动作撤销了。一个分布式的全局事务,整体是两阶段提交的模型。TCC也是一样的,单相对应2PC和3PC来说,把事务管理从数据库层面,提取到了业务层面。
TCC第一阶段:try行为,试探性操作
TCC第二阶段:confirm或cancel操作,第一阶段成功就会调用confirm,失败就会cancel操作
TCC还需要一个全局事务管理者的角色,用来记录TCC全局事务状态并提交或回滚事务
由于TCC每一步操作都需要业务上的定义,对于一个操作都要写三个方法对应try、confirm、cancel。因此TCC对业务的侵入性比较大和业务是紧耦合的关系。但是因为TCC是业务上的实现,所以他的适用范围更广,可以跨数据库、跨不同的业务系统来实现事务。
事务控制代码都需要开发去写,所以需要做好异常控制:
空回滚允许-现象是try没有被执行,就调用了cancel。
出现原因:Try超时(丢包)、分布式事务回滚触发cancel、未收到try收到cancel
解决办法:让cancel能够识别出这是一个空回滚,可以记录事务执行状态,cancel中判断try是否执行了。
幂等控制
事务协调着会重复调用,try、confirm、cancel三个方法都需要实现幂等控制
解决办法:记录事务执行状态,如果执行过了,就不再执行。
防悬挂控制-Cancel比Try先执行
出现原因:Try超时(拥堵)、分布式事务回滚触发cancel、拥堵try到达
解决办法:记录事务执行状态,try执行时判断cancel是否执行了。
并发控制
Doris的事务模型中的Coordinator BE就是TCC中的使用者,FE就是TCC中的事务管理者,Executor BE就是TCC中的服务A。
-
调用者向事务管理者发起事务相当于Coordinator BE节点向FE发送Begin Transaction请求(当然还有向FE获取导入计划的交互流程未体现);
-
调用者向服务调用try,相当于Coordinator BE向Executor BE分发数据;
-
服务向调用者返回结果相当于Executor BE向Coordinator BE返回数据写入成功与否;
-
调用者向事务管理者发送提交命令即是Coordinator BE节点向FE发送Commit Transaction请求;
-
事务管理者向服务调用confirm相当于FE对commit成功的Transaction执行Publish Version,也就是通过Thrift RPC向Executor BE节点下发Publish Version请求。 (当然还有当Executor BE上所有的Publish Version任务执行成功,FE会向Coordinator BE返回Commit Transaction以及Publish Version成功的信息。如果存在某些Publish Version任务失败,FE会向Executor BE节点重复下发Publish Version请求直到之前失败的Publish Version任务成功)
当然对于第四步,调用者向事务管理者发送回滚命令相当于当从FE获取导入计划失败、执行数据导入失败或Commit Transaction失败时,Coordinator BE节点会向FE发送Rollback Transaction请求,执行事务回滚。事务管理者在收到回滚命令后会向服务发送Cancel请求相当于FE收到事务回滚的请求之后,会通过Thrift RPC向Executor BE发送Clear Transaction的请求。