分布式事务,由于我们将单表的数据切片后将存储在多个数据库甚至多个数据库实例中,所以依靠数据库本身的事务机制不能满足所有场景的需要,但是我们推荐在一个数据库实例中的操作尽可能使用本地事务来保证一致性,跨数据库实例的一系列更新操作需要根据事务路由在不同的数据源中完成,各个数据源之间的更新操作需要通过分布式事务处理。
主流的分布式事务解决方案有三种:两阶段提交协议、最大努力保证模式和事务补偿机制。
两阶段提交协议将分布式事务分为两个阶段,一个是准备阶段,一个是提交阶段,两个阶段都由事务管理器发起。基于两阶段提交协议,事务管理器能够最大限度地保证跨数据库操作的事务的原子性,是分布式系统环境下最严格的事务实现方法。两阶段提交协议也带来了性能方面的问题,难于进行水平伸缩,因为在提交事务的过程中,事务管理器需要和每个参与者进行准备和提交的操作的协调,在准备阶段锁定资源,在提交阶段消费资源,但是由于参与者较多,锁定资源和消费资源之间的时间差被拉长,导致响应速度较慢,在此期间产生死锁或者不确定结果的可能性较大。由于两阶段提交协议是阻塞协议,在极端情况下不能快速响应请求方,因此有人提出了三阶段提交协议,解决了两阶段提交协议的阻塞问题,但仍然需要事务管理器在参与者之间协调,才能完成一个分布式事务。
最大努力保证模式,这是一种非常通用的保证分布式一致性的模式,很多开发人员一直在使用,但是并为意识到这是一种模式,该模式适用于对一致性要求并不十分严格,但是对性能要求较高的场景。在更新多个资源时,将多个资源的提交尽量延后到最后一刻处理,这样的话,如果业务流程出现问题,则所有的资源更新都可以回滚,事务仍然保持一致。唯一可能出现问题的情况是在提交多个资源时发生了系统问题,比如网络问题等,但是这种情况是非常罕见的,一旦出现这种情况,就需要进行实时补偿,将已提交的事务进行回滚。
事务补偿机制,在对性能要求很高的场景中,两阶段提交协议并不是一种好方案,最大努力保证模式也会使多个分布式操作互相嵌套,有可能互相影响。
无论使用上面哪种方法实现分布式事务,都需要对分库分表的多个数据源路由事务。如果更新操作在一个数据库实例内发生,便可以使用数据源的事务来处理。对于跨数据源的事务,可通过在应用层使用最大努力保证模式和事务补偿机制来达成事务的一致性。当然,有时我们需要通过编写程序来选择数据库的事务管理器,根据实现方式的不同,可将事务路由具体分为以下三种。一是自动提交事务路由,二是可编程事务路由,三是声明式事务路由。