区块链系统分布式事务解决方案调研

前言

区块链系统是典型的去中心化分布式系统,而分布式系统架构中非常核心的一部分便是分布式事务的实现。在企业级区块链系统中,往往有需要多个数据库来满足系统架构的需要,例如区块信息易保存在k-v数据库中,而区块链系统的业务数据需要保存在传统的关系型数据库中,这种跨数据库、跨服务器的数据操作架构设计对事务的管理要求极高,下面我们讨论一下常见的分布式事务解决方案。

一、数据库事务

1、事物的特性

事务是由一组SQL语句组成的逻辑处理单元,事务具有以下4个属性,通常简称为事务的ACID属性:

原子性(Atomicity):事务是一个原子操作单元,其对数据的修改,要么全都执行,要么全都不执行。

一致性(Consistent):在事务开始和完成时,数据都必须保持一致状态。这意味着所有相关的数据规则都必须应用于事务的修改,以保持数据的完整性;事务结束时,所有的内部数据结构(如B树索引或双向链表)也都必须是正确的。

隔离性(Isoation):数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的“独立”环境执行。这意味着事务处理过程中的中间状态对外部是不可见的,反之亦然。

持久性(Durabe):事务完成之后,它对于数据的修改是永久性的,即使出现系统故障也能够保持。

2、事务类型:

JDBC事务:

即为上面说的数据库事务中的本地事务,通过connection对象控制管理。

JTA事务:

JTA指Java事务API(JavaTransaction API),是Java EE数据库事务规范, JTA只提供了事务管理接口,由应用程序服务器厂商(如WebSphere Application Server)提供实现,JTA事务比JDBC更强大,支持分布式事务。

3、事务种类:

本地事务:

普通事务,独立一个数据库,能保证在该数据库上操作的ACID。

分布式事务:

涉及两个或多个数据库源的事务,即跨越多台同类或异类数据库的事务(由每台数据库的本地事务组成的),分布式事务旨在保证这些本地事务的所有操作的ACID,使事务可以跨越多台数据库。

二、如何保证数据的强一致性

1、本地事务(mysql 之 InnoDB):

InnoDB支持事务,同Oracle类似,事务提交需要写redo、undo。采用日志先行的策略,将数据的变更在内存中完成,并且将事务记录成redo,顺序的写入redo日志中,即表示该事务已经完成,就可以返回给客户已提交的信息。但是实际上被更改的数据还在内存中,并没有刷新到磁盘,即还没有落地,当达到一定的条件,会触发checkpoint,将内存中的数据(page)合并写入到磁盘,这样就减少了离散写、IOPS,提高性能。

在这个过程中,如果服务器宕机了,内存中的数据丢失,当重启后,会通过redo日志进行recovery重做。确保不会丢失数据。因此只要redo能够实时的写入到磁盘,InnoDB就不会丢数据。

2、分布式事务:

多个数据库中的某个数据库在提交事务的时候突然断电,那么它是怎么样恢复的呢? 这也是分布式系统复杂的地方,因为分布式的网络环境很复杂,这种“断电”故障要比单机多很多,所以我们在做分布式系统的时候,最先考虑的就是这种情况。这些异常可能有 机器宕机、网络异常、消息丢失、消息乱序、数据错误、不可靠的TCP、存储数据丢失、其他异常等等…

对分布式系统有过研究的读者, 听说过 “CAP定律”、“Base理论” 等,这里不对这些概念做过多的解释,有兴趣的读者可以查看相关参考资料 。

在分布式系统中,同时满足 “CAP定律” 中的 “一致性”、“可用性” 和 “分区容错性” 三者是不可能的, 根据不同的业务场景使用不同的方法实现最终一致性,可以根据业务的特性做部分取舍,在业务过程中可以容忍一定时间内的数据不一致。

三、实现分布式事务常见方案对比

1、基于XA协议的两阶段提交(2PC)

XA 是由 X/Open 组织提出的分布式事务的规范

XA 规范主要 定义了 ( 全局 ) 事务管理器 ( Transaction Manager ) 和 ( 局部 ) 资源管理器 ( Resource Manager ) 之间的接口。 XA 接口是双向的系统接口,在事务管理器(Transaction Manager)以及一个或多个资源管理器(Resource Manager)之间形成通信桥梁。 XA 之所以需要引入事务管理器是因为,在分布式系统中,从理论上讲(参考Fischer等的论文),两台机器理论上无 法达到一致的状态,需要引入一个单点进行协调。 事务管理器控制着全局事务,管理事务生命周期,并协调资源。资源管理器负责控制和管理实际资源(如数据库或 JMS队列)。下图说明了事务管理器、资源管理器,与应用程序之间的关系:
区块链系统分布式事务解决方案调研_第1张图片

在 JavaEE 平台下,WebLogic、Webshare 等主流商用的应用服务器提供了 JTA 的实现和支持。而在 Tomcat 下是没有实现的(Tomcat 不能算是 JavaEE 应用服务器,比较轻量),这就需要借助第三方的框架 Jotm、Automikos 等来实现,两者均支持 Spring 事务整合。

在分布式事务的控制中采用了两阶段提交协议(Two- Phase Commit Protocol)。即事务的提交分为两个阶段:

  • 预提交阶段(Pre-Commit Phase)

  • 决策后阶段(Post-Decision Phase)

为了支持两阶段提交,一个分布式更新事务中涉及到的服务器必须能够相互通信。一般来说一个服务器会被指定为"控制"或"提交"服务器并监控来自其它服务器的信息。

在一个分布式事务中,必须有一个场地的Server作为协调者(coordinator),它能向 其它场地的Server发出请求,并对它们的回答作出响应,由它来控制一个分布式事务的提交或撤消。该分布式事务中涉及到的其它场地的Server称为参 与者(Participant)。
区块链系统分布式事务解决方案调研_第2张图片

2、补偿事务(TCC)

TCC 其实就是采用的补偿机制,其核心思想是:针对每个操作,都要注册一个与其对应的确认和补偿(撤销)操作。它分为三个阶段:

  • Try 阶段主要是对业务系统做检测及资源预留
  • Confirm 阶段主要是对业务系统做确认提交,Try 阶段执行成功并开始执行 Confirm 阶段时,默认Confirm 阶段是不会出错的。即:只要 Try 成功,Confirm 一定成功。
  • Cancel 阶段主要是在业务执行错误,需要回滚的状态下执行的业务取消,预留资源释放。

举个例子,假入 Bob 要向 Smith 转账,思路大概是:我们有一个本地方法,里面依次调用

1、首先在 Try 阶段,要先调用远程接口把 Smith 和 Bob 的钱给冻结起来。

2、在 Confirm 阶段,执行远程调用的转账的操作,转账成功进行解冻。

3、如果第2步执行成功,那么转账成功,如果第二步执行失败,则调用远程冻结接口对应的解冻方法 (Cancel)。

优点: 跟 2PC 比起来,实现以及流程相对简单了一些,但数据的一致性比 2PC 也要差一些。

账成功,如果第二步执行失败,则调用远程冻结接口对应的解冻方法 (Cancel)。

优点: 跟 2PC 比起来,实现以及流程相对简单了一些,但数据的一致性比 2PC 也要差一些。

缺点: 缺点还是比较明显的,在2,3步中都有可能失败。TCC 属于应用层的一种补偿方式,所以需要程序员在实现的时候多写很多补偿的代码,在一些场景中,一些业务流程可能用 TCC 不太好定义及处理。

你可能感兴趣的:(区块链技术,区块链,分布式)