我们了解了账户系统,学习了数据库事务,事务解决了交易类系统的数据一致

但是如果需要跨系统,跨数据库的时候,单一的数据库事务就没法解决了

而且,现在更加靠近云原生和微服务,微服务就是将大的系统打散为小的服务,然后每个服务具有自己的数据库,数据库也更加分散

分布式事务这种问题,可不能和数据库那样,在开始和结尾加上begin和commit就可以了

我们简单说下在微服务的交易系统中,面临的分布式数据一致问题

关于分布式事务的概念

分布式事务,很少有合适的框架,阿里的seata可以算是一个,但是本质上,使用的方案还是源于2PC,3PC,TCC,Saga和本地消息表,这些方法,强项和弱项不一样,适用的场景也不一样,这些事务面对的问题也不一样

首先是订单和优惠券的数据一致性问题

这个问题是常见的,可以使用2PC解决的问题,如果使用了优惠券,订单系统和优惠券系统都需要更新这个使用操作

订单需要,在订单中写入相关的优惠券数据

订单表中写入订单数据

然后优惠券系统,需要将这张优惠券的状态更新为了已使用

然后将这两个系统的数据更新操作保持一致,要么都更新成功,要都更新失败

2PC就是需要一个事务协调者的角色,来协调订单系统和优惠券系统,协调者提供一个服务入口,内部分别调用不同的服务

在这个二阶段提交的过程中,准备阶段,协调者分别给订单系统和优惠券系统发送准备的命令,都收到准备命令后,进行执行准备操作,分别开启事务,然后执行录入记录,

然后返回给协调者,准备完成,收到两个准备完成后,进入提交阶段,这一阶段不能返回,这一阶段就是每个系统自己负责提交自己的数据库事务,等到所有的协调者都返回提交成功,事务就完成了

图片

异常情况下,如果在准备阶段出现错误,就统一回滚事务

如果提交阶段出现了错误,就只有华山一条路,必须要不断重试了

而且,如果不是重的操作,完全可以在一起做协调操作

减少参与分布式事务的进程

减少了远程调用,性能更好

2PC是一种强一致性的设计,保证了原子性和隔离性,只要2PC事务完成,就一定是一致的状态

这种适用于强一致性的场景,因为如果一致性不高,可能会被黑产利用,一张优惠券反复使用

对于一些不太需要强一致性的场景,我们可以考虑使用本地消息表来解决,

本地消息表主要的应对场景是保证数据的最终一致性,在购物流程,用户在购物车选好了商品,点击结算去创建订单,这个过程我们的系统做了两件事

1.订单系统创建了新的订单,订单的商品就是勾选的商品

2.将勾选的商品从购物车中删除

分布式事务问题,需要保证这两个操作都执行,但是对于这两个操作的一致性要求并不高,所以,我们可以使用本地记录表,我们在执行这个数据库事务在过程中,在订单系统更新完成后,将一个清理购物车的操作,记录在本地,在这里面没有分布式的问题,就是一个普通的单机事务,这就可以直接返回成功了

然后我们使用其他的线程,去读取这个本地消息,调用接口清理购物车,而且这个清理购物车的操作,完全可以通过重试来解决

这个本地消息表,可以考虑保存在数据库,或者保存在消息队列,从而达到最终一致性

最后就是一个生成订单的时候,需要锁定库存

这个操作不能接受使用本地消息表,不然会出现用户下单完成了,系统异步任务去锁定库存的时候,缺货导致锁定失败,就很难处理了

发表评论

邮箱地址不会被公开。 必填项已用*标注