沈剑分布式事务原来可以这么玩
多个数据要同时操作,如何保证数据的完整性,以及一致性?
答:事务,是常见的做法。
举个 栗子:
用户下了一个订单,需要修改余额表,订单表,流水表,于是会有类似的伪代码:
start transaction;
CURD table t_account; any Exception rollback;
CURD table t_order; any Exception rollback;
CURD table t_flow; any Exception rollback;
commit;
-
如果对余额表,订单表,流水表的SQL操作全部成功,则全部提交
-
如果任何一个出现问题,则全部回滚
事务,以保证数据的完整性以及一致性。
事务的方案会有什么潜在问题?
答:互联网的业务特点,数据量较大,并发量较大,经常使用拆库的方式提升系统的性能。如果进行了拆库,余额、订单、流水可能分布在不同的数据库上,甚至不同的数据库实例上,此时就不能用数据库原生事务来保证数据的一致性了。
高并发易落地的分布式事务,是行业没有很好解决的难题,那怎么办呢?
答:补偿事务是一种常见的实践。
什么是补偿事务?
答:补偿事务,是一种在业务端实施业务逆向操作事务。
举个栗子:
修改余额, 事务 为:
int Do_AccountT(uid, money){
start transaction;
//余额改变money这么多
CURD table t_account with money for uid;
anyException rollback return NO;
commit;
return YES;
}
那么, 修改余额, 补偿事务 可以是:
int Compensate_AccountT(uid, money){
//做一个money的反向操作
return Do_AccountT(uid, -1*money){
}
同理, 订单操作, 事务 是:Do_OrderT,新增一个订单;
订单操作, 补偿事务 是:Compensate_OrderT,删除一个订单。
要保证余额与订单的一致性,伪代码:
// 执行第一个事务
int flag = Do_AccountT();
if(flag=YES){
//第一个事务成功,则执行第二个事务
flag= Do_OrderT();
if(flag=YES){
// 第二个事务成功,则成功
return YES;
}
else{
// 第二个事务失败,执行第一个事务的补偿事务
Compensate_AccountT();
}
}
补偿事务有什么缺点?
-
不同的业务要写不同的补偿事务,不具备通用性;
-
没有考虑补偿事务的失败;
-
如果业务流程很复杂,if/else会嵌套非常多层;
画外音:上面的例子还只考虑了余额+订单的一致性,就有22=4个分支,如果要考虑余额+订单+流水的一致性,则会有22*2=8个if/else分支,复杂性呈指数级增长。
还有其它简易一致性实践么?
答:多个数据库实例上的多个事务,要保证一致性,可以进行“后置提交优化”。
单库 是用这样一个大事务保证一致性:
start transaction;
CURD table t_account; any Exception rollback;
CURD table t_order; any Exception rollback;
CURD table t_flow; any Exception rollback;
commit;
拆分成了多个库后,大事务会变成三个小事务:
start transaction1;
//第一个库事务执行
CURD table t_account; any Exception rollback;
…
// 第一个库事务提交
commit1;
start transaction2;
//第二个库事务执行
CURD table t_order; any Exception rollback;
…
// 第二个库事务提交
commit2;
start transaction3;
//第三个库事务执行
CU
- 原文作者:知识铺
- 原文链接:https://index.zshipu.com/geek/post/%E4%BA%92%E8%81%94%E7%BD%91/%E6%B2%88%E5%89%91%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1%E5%8E%9F%E6%9D%A5%E5%8F%AF%E4%BB%A5%E8%BF%99%E4%B9%88%E7%8E%A9/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。
- 免责声明:本页面内容均来源于站内编辑发布,部分信息来源互联网,并不意味着本站赞同其观点或者证实其内容的真实性,如涉及版权等问题,请立即联系客服进行更改或删除,保证您的合法权益。转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。也可以邮件至 sblig@126.com