分布式事务,如何保证多个系统数据的一致性
如果一笔交易涉及到跨多个数据库、多个系统的时候,单一的数据库事务就无法满足需求了。
那如何解决跨库数据一致性的问题呢?你首先想到肯定是 :分布式事务
分布式环境下这事可能就没这么简单!
分为分布式环境,一个交易将会被分在多个不同系统中,多个微服务进程中计算,在多个数据库中执行更新操作。所以并没有什么分布式事务或者组件能在分布式环境下,提供接近单库事务一致性的保证。
那么 分布式事务到底有哪些解决方案呢?
分布式事务的解决方案有很多,比如:2PC、3PC、TCC、Saga 和本地消息表等等。
2PC:订单与优惠券的数据一致性问题
二阶段提交,所谓两阶段就是 :准备阶段、提交阶段
准备阶段:协调者分别向订单系统 优惠券系统发送准备指令,比如开始事务、插入数据最后返回准备成功。
协调者根据收到的 准备成功信息,进行下一步的操作。
提交阶段就比较简单了,就是给两个系统发送提交指令。
收到成功后,整个分布式事务就结束了,这是正常的情况,如果出现了异常了怎么办?
分两个阶段:
提交阶段如果任何一方没有正确返回准备成功,则协调者发送回滚指令,准备阶段的数据进行回滚。
如果进入了提交阶段,这个时候就只能成功。
其实,提交阶段因为网络服务等种种原因,还是有可能失败,但是,提交其实是一个快速,轻量级的操作,失败的概率很小,实际的一致性还是非常好的。
是不是没有缺点呢?当然不是:
一是,事务执行的过程会阻塞服务端的线程和数据库的会话,所以并发场景性能不会高。
二是,协调者一个单点,一旦宕机就会阻塞提交操作。
所以只有在强一致,并发量不高的情况下才会考虑使用。
本地消息表:订单与购物车数据的一致性
我们在购物车加入商品后,点击结算会进入订单页面,这个过程我们做了两个事情:
一是,清空购物车商品
二是,创建商品订单
这两个操作也是要么成功要么失败,但是有一点你 要注意:
购物车商品的清空,不是强一致的呀,不像 订单和优惠券的的操作。
晚个几秒再清空购物车没什么影响,本地表就非常适合这种分布式最终一致性。
思路是这样的:
当创建订单的事后,可以在同一个事务中记录一张本地消息表,与订单在同一个数据库事务中。然后开始一个异步服务去清空购物车,如果更新失败还可以进行重试,直到成功。
使用本地消息表的前提就是,清空购物车的操作不能依赖其他需要锁定的资源。
网友评论