跨库事务一致性问题的解决方式(例)

    我们看一个跨库事务一致性的问题,这是一个简单的场景:有新老两个系统。相应新老两套数据库。新数据库採用分库分表的设计。考虑到项目公布之后可能存在风险,採取了新老系统的并行方案。这个系统的业务比較简单:接收来自外部的数据。然后对数据进行核对处理。为了保证新老系统可以并行。在接收数据的时候必须实现双写方案,从而导致了跨库事务的一致性问题。

    以下一幅图展示这一简单的场景

    这里面会存在一个小问题,就是可能存在写入老库成功,可是写入新库失败的场景。

    我们假设出现这样的概率的情况是百万分之中的一个,在系统公布的情况下,这样的概率可能更高。从眼下我们的数据量来看,一天大概5000W。那么出现不一致的数据量在500条。

考虑到这个是数据核算系统,不能有一条丢失的情况,否则两边比对结果可能会不一致。所以须要保证一致性。

    这样的问题,有以下几种解决方式

1 考虑使用JTA等支持分布式事务的事务管理器

这样的方案的优势就是直接有现成的解决方式,一般的j2eeserver都提供了JTA的相关的实现。比較明显的问题就是解决方式太重量级。一般JTA除了server要支持,相应的数据库服务厂商一般也要提供相应的商业支持。主要是提供基于 XAResource  JDBC驱动,这一些商业上的支持,部分是须要付费的。

并且使用XA 数据库驱动,本身可能导致一些潜在的问题,尤其是基于不同的数据库厂商的时候。而XA是基于两阶段提交协议。事务管理器为了完毕一个事务,须要多次和数据库通信,效率上比較低。

2 考虑使用数据库自身的数据同步机制

    假设新老库的结构基本一样,这样的方案还是比較靠谱的。

也是比較简单的方案。

这样的方案的局限性也再次。在本项目中。新库不是一个物理库。而是多个物理库,而老库是一个物理库。

假设要用数据库自身的同步机制,涉及到多个库和一个库之间的数据复制。同一时候因为分表的方案也不一样,导致两边做一个映射的配置,而这个须要在数据库层面进行,逻辑相当的复杂。解决方式成本也比較高。

相当于把重要的分库分表的逻辑在数据库这一层又一次实现了一份。

    事实上这个也带来一个维护问题。一旦我们认为新系统已经足够稳定。

应用程序可以之间在写入库进行切换,把老库的逻辑切掉,从而实现了仅仅写新库的需求。整个过程也不须要进行再次公布。而数据库的方案则须要停掉脚本,在多个地方进行配置。

3 在old库存放同样的两张模型表。一张表用于old库的持久化表。另外一张作为暂时表,主要是作为须要同步到到新库的数据。

假设已经同步到新库。就删除。假设没有同步到新库就同步到新库。这个过程採用定时机制,每分钟定时提取暂时表一定数据量的数据。批量导入到新库。

通过努力重试,来保证一致性。而新库则须要保证幂等性。保证数据仅仅会同步过一次。普通情况下,则是通过数据特征标识符来识别,这个一般都是数据的唯一性主键。

    以下是简单的实现:

    这三种方案的主要思想就是 採取重试机制,这个仅仅是分布式事务里面的一种模型,相应的还有两阶段提交,异常恢复补偿等机制。

原文地址:https://www.cnblogs.com/blfshiye/p/5397576.html