TX-LCN优化介绍

最新方案原理图

最大差异是在最后TM通知发起方时,要求事务发起方再反馈给TM一条消息(图中第13条),其他方面跟5.0之前的版本类似。
TX-LCN优化介绍_第1张图片
LCN优化主要在以下几点:

  1. 支持四种事务模式

    LCN-JDBC代理(包括 柔性事务模式、强一致事务模式 两种)

    MQ的消息事务

    TCC

  2. 基于P2P网络架构的中心化负载集群方案

  3. 根据spanner论文中关于true time的时间锁协调提交方案

LCN-JDBC代理原理(强一致)

LCN的强一致事务模式 是在LCN的原理基础之上改良的。

下面的流程图对应上方原理图的执行业务的各个阶段(2、4、7)做的处理。

业务方法 可以是事务发起方 也可以是事务参与方。业务方法先执行开启事务的方法,开启事务通过JDBC操作传播给LCN代理连接池。代理连接池会拿到数据库连接池的连接,继续请求拿到数据库真正的连接,然后在代理连接池中做代理,把代理之后的连接对象返回给业务。业务在执行JDBC操作时就是用代理的连接对象操作的。

执行业务时,相比之前的方案,会多做一步——对执行业务的SQL进行解析。此处的解析不是SQL的逆向(即 不是TXC事务模式的那种方案),只是做一个数据库解析的操作,就是解析成实际要执行到数据库中的更新语句。当业务执行完毕后,会拿到整个业务执行的所有SQL。在本地事务做提交时,代理连接池hold住了数据库的连接,把所保存的这些SQL进行伪提交并计时。此处的计时机制就是等待TM给响应通知事务提交或回滚,若TM迟迟不给通知,会主动去请求。

TM主动给出响应通知:

​ 当TM收到事务发起方对事务下达的命令后,TM根据事务具体要提交还是回滚 对各个模块进行通知。

​ 各模块要进行提交时,首先生成一个对于之前“解析执行的SQL并保存起来”的delete语句,把这语句也加入到本次要提交的事务中(即 这次事务多了一条删除所保存的SQL的语句),然后再发起事务提交。若事务已真正提交到数据库,在解析SQL时所存储的SQL信息也就不存在了。这样做的优点是:①可以通过看保存的SQL日志信息来判断该事务有没有提交,包括一些在网络或数据库故障导致提交失败的情况。②如果TM通知业务模块时 业务模块挂了,则有可能在对其通知消息时发起多次请求,而此处这样处理可保证在发起多次请求时只可能提交一次,原因是 提交了一次之后,存储的日志SQL信息就不存在,不可能再提交一次了。

​ 若TM发送了通知事务却没有接收到TC的响应事务(TC确认自己已提交本地事务后才给响应),可能的原因有:①TC故障了②网络问题,通知不到③TC的数据库出了问题 提交不了事务。出现这种情况TM会重试一下通知,若依然没有响应,会去请求它的负载模块。联系负载模块的结果又分为两种①原模块挂了,则负载模块有可能提交成功②原模块没有挂,则负载模块会提交失败,因为代理连接池hold住了连接,负载模块是没有办法做提交的,而且会触发数据库锁的问题。因此负载模块收到TM的通知事务时,就算能查询到数据,在做提交时会因原模块的锁没有释放而提交失败。
​ 对于第②种情况,原模块既然没有挂,可能是数据库挂了或网络故障,此时TM会不断地重试通知原模块,直到超过计时的时间(TM是知道每个模块的计时时间的)。接下来TM会自动对数据进行补偿处理并记录一下。如果真的是数据库挂了,等TC自己也到了超时时间去询问TM时,发现TM已经对其进行了记录补偿的操作,自己提交事务也无法成功,此时TC也不再提交事务,而是做补偿。

业务模块等不到TM的响应通知,触发超时机制:

​ 若业务模块能连接上TM,一般会收到TM“继续等待”的指令,计时器重新计时;若TC网络故障或者TM挂了导致连接不上,会先切换与TM的连接(TM做了负载的话),若确实所有TM都连接不上,则TC会把本地事务做回滚,回滚操作不会删除“解析执行的SQL”阶段所保存的SQL日志。这样当TM能够联系上时,就可以通过这些保存的要执行的SQL日志做一次补偿,这种方式比之前“重现调用链”的方式更佳、
TX-LCN优化介绍_第2张图片

LCN-JDBC代理原理(柔性事务)

弱性事务与强性事务的流程主要区别在业务模块本地提交事务时,LCN代理连接池是“事务伪提交,开始计时”还是“事务回滚,释放资源,开始计时”,其他情况与可能出现的问题与强性事务模式类似。

柔性事务此处的“回滚”只是对业务本地的事务做回滚操作,但实际要执行的SQL还是存下来了的。事务回滚后连接资源也释放掉,开始计时。

TM在去通知事务提交时,只需要从保存的SQL日志中查询到要执行的SQL,再加上一条删除这些SQL日志的SQL,作为一个事务一起提交到数据库中。数据库提交成功后的效果是 sql日志已经不存在且业务已经执行成功。
TX-LCN优化介绍_第3张图片

MQ事务消息

RabbitMQ和kafka的0.11版本之后 本身已经支持了事务消息。而此处不基于MQ本身已经实现的事务消息的方式,对MQ的消息队列也做了封装,这样无论MQ是否支持消息,都可以完成事务的协调。

【接收事务消息】业务方法接收别人发来的消息并消费该消息(该消息指的是事务消息,非事务消息不会走以下流程)。

【检查事务消息】业务方法接收事务消息后,先检查该消息是否已执行过,若已执行过,则直接中止该消息的业务处理,并把状态改为已消费。(LCN代理连接池拿到该消息,去请求TM,判断一下TM是否已经把它记为消费过。若是,则记为已消费,响应给LCN代理连接池,然后结束;若没有被消费过,则业务方法开始执行业务)。

【保存待执行事务消息】业务方法在开始执行业务时,先把这条未被消费的消息 产生一条消息的数据 存到数据库中。该数据库是与业务方一起的本地数据库中,即 MQ需要依赖数据库操作。

【创建事务消息】消息数据已保存到数据库里,业务方真正开始执行其业务的过程中,如果需要调用其他模块,比如A调用B B调用C,调用时要给被调用模块发送一条事务消息,业务逻辑里会有一行“给被调用模块发送消息”的代码。执行这行代码时在本地先创建一个待发送的消息 并本地保存提交之后,会把这个消息通知给TM,TM也会存下该消息,然后响应给LCN代理连接,进而响应给业务方。这个阶段属于preview阶段,即 该消息实际上没有发送出去,但该消息已经把它记进来了,只有在业务方法本地事务提交的时候才会发送出去,这样就做到了消息与本地事务的一致性控制。我们不控制MQ的事务提交,只控制事务成功或失败时该消息的发送操作。

【本地事务提交】当业务方法进行本地事务提交时,若提交成功,会修改“保存待执行业务消息”过程中的标识为“执行过”,代理连接池去通知TM,TM修改该消息状态为待发送,发送事务消息,响应本地业务。如果该过程出现问题,LCN连接池会不断地进行重试确认事务消息,若超过设定的时间依然没有重试成功,会抛出异常,整个事务做事务回滚,TxManager对MQ的消息也不会真正地发送出去,不会影响到消息的传播。

【删除消息】当TM成功地将事务消息发送出去,并成功地响应事务确认给发起方,此时LCN代理会把该本地事务消息删除(删掉的是“LCN代理连接池 创建消息”过程中所创建的消息)。

特殊情况:

如果该服务模块发送给TM之后,还没得到TM响应时 该服务挂掉(即:发送了“确认事务消息(重试)”,但在收到“响应事务确认”之前挂掉),当该模块再次启动时会先检查本地数据,只要发现有消息没有删除,就主动去请求TM(即 再次重试确认事务消息),重试成功了再删除所创建的事务消息。这个过程中,可能出现TM把同一个事务消息发出去两遍的情况,但由于接收事务消息的模块在刚接到消息时会有事务消息检查,因此重复发送也没关系。

TX-LCN优化介绍_第4张图片

TCC

TCC模式主要靠业务逻辑自行实现,框架只是做到“通知到”就可以。因此业务执行的准确性基本与框架无关,主要看业务代码是否考虑周到。

你可能感兴趣的:(LCN,LCN,TX-LCN,分布式事务)