互联网一致性架构设计 -- 事务一致性

互联网一致性架构设计 -- 事务一致性

按业务区分

  • 单库事务
  • 多库事务

    例子:用户下了一个订单,需要修改余额表,订单表,流水表

    单库事务

start transaction;
         CURDtable t_account;  any Exception rollback;
         CURDtable t_order;       any Exceptionrollback;
         CURDtable t_flow;         any Exceptionrollback;
commit;

    多库事务:将缘分一起执行的事务,拆分成多个小的

start transaction1;
         //第一个库事务执行
         CURDtable t_account;  any Exception rollback;
         …
// 第一个库事务提交
commit1;
start transaction2;
         //第二个库事务执行
         CURDtable t_order;       any Exceptionrollback;
         …
// 第二个库事务提交
commit2;
start transaction3;
         //第三个库事务执行
         CURDtable t_flow;         any Exceptionrollback;
         …
// 第三个库事务提交
commit3;

    结果:分库后分成了多个小的事务,就不能实现原子性,无法达到事务的效果。

优化方案

  • 补偿事务
  • 先执行完,最后一起提交

    补偿事务

    

       补偿事务是一种在业务端实施业务逆向操作事务,来保证业务数据一致性的方式。

    例如:

举个栗子,修改余额表事务为
int Do_AccountT(uid, money){
start transaction;
         //余额改变money这么多
         CURDtable t_account with money;       anyException rollback return NO;
commit;
return YES;
}
 
那么补偿事务可以是:
int Compensate_AccountT(uid, money){
         //做一个money的反向操作
         returnDo_AccountT(uid, -1*money){
}

    缺点:

  1. 不同的业务要写不同的补偿事务,不具备通用性
  2. 没有考虑补偿事务的失败
  3. 如果业务流程很复杂,if/else会嵌套非常多层

    先执行完,最后一起提交

    依然是这个拆分后的几个小事务

start transaction1;
         //第一个库事务执行
         CURDtable t_account;  any Exception rollback;
         …
// 第一个库事务提交
commit1;
start transaction2;
         //第二个库事务执行
         CURDtable t_order;       any Exceptionrollback;
         …
// 第二个库事务提交
commit2;
start transaction3;
         //第三个库事务执行
         CURDtable t_flow;         any Exceptionrollback;
         …
// 第三个库事务提交
commit3;

    优化前

trx1.exec();
trx1.commit();
trx2.exec();
trx2.commit();
trx3.exec();
trx3.commit();

第一个事务执行200ms,提交1ms;
第二个事务执行120ms,提交1ms;
第三个事务执行80ms,提交1ms;

    优化后

trx1.exec();
trx2.exec();
trx3.exec();
trx1.commit();
trx2.commit();
trx3.commit();

第一个事务执行200ms;
第二个事务执行120ms;
第三个事务执行80ms;
第一个事务执行1ms;
第二个事务执行1ms;
第三个事务执行1ms;

    为什么这么做?

       优化前:第一个事务成功提交之后,最后一个事务成功提交之前,如果出现问题(例如服务器重启,数据库异常等),都可能导致数据不一致。这个时间比较长,共403ms。

       优化后:第一个事务提交后的,最后一个事务提交前,这个时间比较短,共3ms,这样就能尽可能减少出现数据不一致的概率。而且还通用,减少编码量。

    缺点:还是存在不一致的情况,但是已经大大降低。

两种优化方案的比较

       事务提交时会释放数据库的连接,第一种方案,第一个库事务提交,数据库连接就释放了,后置事务提交的方案,所有库的连接,要等到所有事务执行完才释放。这就意味着,数据库连接占用的时间增长了,系统整体的吞吐量降低了。

猜你喜欢

转载自youyu4.iteye.com/blog/2393735