60 lines
4.3 KiB
Markdown
60 lines
4.3 KiB
Markdown
- [seata](#seata)
|
||
- [Seata Global Exclusive Write Lock](#seata-global-exclusive-write-lock)
|
||
- [TC - Global Exclusive Write Lock Implementation](#tc---global-exclusive-write-lock-implementation)
|
||
- [RM - Global Exclusive Write Lock Usage](#rm---global-exclusive-write-lock-usage)
|
||
|
||
|
||
# seata
|
||
seata作为兼具高性能和易用性的分布式事务解决方案,适用于微服务架构。
|
||
|
||
在使用seata的系统中,事务隔离级别如下:
|
||
- `branch transaction`/`local transaction`:在seata系统中,分支事务/本地事务的隔离级别为read committed
|
||
- `global transaction`:在seata系统中,全局事务的隔离级别为read uncommitted
|
||
- `global transaction`隔离级别为read uncommitted的含义如下:在全局事务尚未提交时,如果分支事务提交,则分支事务的修改对分布式系统外的其他事务可见
|
||
|
||
故而,在分布式系统中,若全局事务的隔离级别为read uncommitted,且没有其他机制用于修复该问题,其将会造成如下问题:
|
||
<img src="https://yqintl.alicdn.com/3588613a02db62c2b534a61984145bbdc6394811.png" alt="1" title="1">
|
||
|
||
在上图所示中,全局事务A和全局事务B对相同的资源R进行了修改,并且分支事务A1和分支事务B1都本地提交,之后,全局事务A回滚,全局事务B提交,那么A无法将资源R回滚到一个合适的状态(例如,A1先对R进行修改,B1后对R进行修改,如果将R恢复到A1修改之前,那么B1对R的修改就会丢失)。
|
||
|
||
## Seata Global Exclusive Write Lock
|
||
`Seata Global Exclusive Write Lock`的代码实现位于`TC`(Transaction Coordinator) module中,RM(Resource Manager)module将会在`需要获取global lock`时对TC module进行请求,进而保证事务之间的写隔离。
|
||
|
||
故而,Seata Global Exclusive Write Lock会在TC module中被实现,并在RM module中被使用。
|
||
|
||
## TC - Global Exclusive Write Lock Implementation
|
||
在TC module中,RpcServer用于处理communication protocol related logic,而TC module实际的处理逻辑则由`DefaultCoordinator`进行处理。
|
||
|
||
> `DefaultCoordinator`中包含了TC module所有向外暴露的方法,例如
|
||
> - doGlobalBegin: 创建全局事务
|
||
> - doGlobalCommit: 提交全局事务
|
||
> - doGlobalRollback: 全局事务回滚
|
||
> - doBranchReport: branch transaction状态report
|
||
> - doBranchRegister:branch transaction注册
|
||
> - 在AT中,branch register会在local transaction提交时进行,执行brach register时会实际占用global exclusive write lock
|
||
> - doLockCheck:global exclusive write lock校验
|
||
>
|
||
> 实际上,上述方法都会被委托给`DefaultCore`来执行
|
||
|
||
在TC端的实现中,所有`获取锁`和`校验锁`的请求都最终会被`LockManger`执行,所有关于global exclusive write lock的设计都被维护在DefaultLockManagerImpl中。
|
||
|
||
## RM - Global Exclusive Write Lock Usage
|
||
在RM module中,主要会使用两个global write lock相关的方法:
|
||
- 校验是否global lock可以被获取
|
||
- 注册transaction branch,并实际获取global lock
|
||
|
||
> 在RM端,针对global exclusive write lock的check和获取大多通过Statement和Connection的代理对象来实现。例如,在`ConnectionProxy.commit`中调用`registerBranch`,从而实现对lock的实际占用。
|
||
|
||
global write lock的释放和RM无关,当全局事务提交时,全局事务相关的global lock将会自动被TC module释放。当注册分支事务之前,会检查global lock状态,确定在branch register的过程中不会发生锁冲突。
|
||
|
||
当执行update、insert、delete语句时,在执行前后都会以undo log的形式生成data snapshot,并且,生成快照的形式会基于`select ... for update`。
|
||
|
||
在本地事务执行提交操作时,会执行branch register操作,该操作中会向TC module发送请求,要求占用global write lock。
|
||
|
||
故而,通过global write lock机制,seata能够保证全局事务未提交前,分支事务占用的锁资源并不会被释放,全局事务外的其他事务想要访问数据时,首先需要校验是否global exclusive write lock已经被占用,上述流程能够保证全局事务能够正确的回滚。
|
||
|
||
但是,在全局事务提交前,其他事务必须等待global exclusive write lock的释放,这种等待会带来性能损耗。
|
||
|
||
|
||
|