LCN 原理
背景
LCN 名称是由早期版本的 LCN 框架命名,在设计框架之初的1.0~2.0的版本时框架设计的步骤是如下,各取其首字母得来的 LCN 命名。
- 锁定事务单元(Lock)
- 确认事务模块状态( Confirm)
- 通知事务( Notify)
框架定位
LCN 并不生产事务,LCN 只是本地事务的协调工。TX-LCN 定位于一款事务协调性框架,框架其本身并不操作事务,而是基于对事务的协调从而达到事务一致性的效果。
事务控制原理
TX-LCN由两大模块组成, TxClient、 TxManager。
TxClient 作为模块的依赖框架,提供 TX-LCN 的标准支持, TxManager 作为分布式事务的控制方。事务发起方或者参与方都由 TxClient 来控制。
通过代理 Connection 的方式实现对本地事务的操作,然后在由 TxManager 统一协调控制事务。当本地事务提交回滚或者关闭连接时将会执行假操作,该代理的连接将由 LCN 连接池管理。
原理图

配置
依赖配置
<!--lcn事务-->
<dependency>
<groupId>com.codingapi.txlcn</groupId>
<artifactId>txlcn-tc</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>com.codingapi.txlcn</groupId>
<artifactId>txlcn-txmsg-netty</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
启动类配置
添加注解
@EnableDistributedTransaction
使用
配合 Dubbo 使用:
服务提供方
@com.alibaba.dubbo.config.annotation.Service
public class LcnReceiveServiceImpl implements ReceiveService {
@Autowired
private JdbcTemplate jdbcTemplate;
@LcnTransaction
public void receiveMoney(int money) {
int resultUser = jdbcTemplate.update("INSERT INTO bank_b(money,user_name)VALUES (?,?)",money,"peter");
System.out.println(TracingContext.tracing().groupId());
}
}
服务发现方
@Service
public class DubboTransferService implements TransferService{
@Autowired
private JdbcTemplate jdbcTemplate;
@Reference
private ReceiveService receiveService;
@LcnTransaction
public String transfer(int money) {
int resultUser = jdbcTemplate.update("INSERT INTO bank_a(money,user_name)VALUES (?,?)",-money,"james");
System.out.println(TracingContext.tracing().groupId());
receiveService.receiveMoney(money);//隐藏地传递了groupid
if (money > 20){
throw new RuntimeException("money too large");
}
return resultUser+"-";
}
}
可以看到,LCN 框架使用起来非常简单。在两个应用中,分别在方法上加上 @LcnTransaction 注解就可以了。这样,这两个事务就在同一个事务组里,要么 2 个事务都成功,要么都失败。
该模式缺陷在于代理的连接需要随事务发起方一起释放连接,增加了连接占用的时间。
TCC 原理
前面的 LCN 依赖包,其实也实现了 TCC 事务。
思想
TCC其实就是采用的补偿机制,其核心思想是:针对每个操作,都要注册一个与其业务逻辑对应的确认和补偿(撤销)操作。
其将整个业务逻辑的每个分支显式的分成了 Try、 Confirm、 Cancel 三个操作。Try 部分完成业务的准备工作, Confirm 部分完成业务的提交, Cancel 部分完成事务的回滚。
原理图

使用
服务提供方
@com.alibaba.dubbo.config.annotation.Service
public class TccReceiveServiceImpl implements ReceiveService {
@Autowired
private JdbcTemplate jdbcTemplate;
//try
@TccTransaction(confirmMethod = "confirm", cancelMethod = "cancel", executeClass = TccReceiveServiceImpl.class)
public void receiveMoney(int money) {
String groupId = TracingContext.tracing().groupId();
int resultUser = jdbcTemplate.update("INSERT INTO bank_b(money,user_name,status)VALUES (?,?,?)",money,"peter",groupId);
}
public void confirm(int money) {
String groupId = TracingContext.tracing().groupId();
int resultUser = jdbcTemplate.update("UPDATE bank_b SET status = 1 WHERE status = ?", tracing().groupId());
}
public void cancel(int money) {
String groupId = TracingContext.tracing().groupId();
int resultUser = jdbcTemplate.update("INSERT INTO bank_b(money,user_name,status)VALUES (?,?,?)",-money,"peter",groupId);
}
}
可以看到,和 LCN 相比,程序员需要写大量的补偿方法,这是它的缺点。
它的优点和 LCN 一样,没有实现真正的 “事务”。真正的事务,如 “二阶段提交”、“三阶段提交”,对响应时间上不如 LCN、TCC 这种变相实现的 “事务”。
关于 “二阶段提交”、“三阶段提交”,见
zookeeper 相关协议、集群特点
1067

被折叠的 条评论
为什么被折叠?



