Apache Ignite事务架构

在本文中,我们将研究事务如何在Apache Ignite中工作我们将不讨论键值存储的概念,而是直接介绍如何在Ignite中实现它。让我们从体系结构的概述开始,然后使用跟踪说明事务逻辑的关键点。通过简单的示例,您将看到事务如何工作(以及由于什么原因它们可能无法工作)。



除了需要:Apache Ignite集群



Ignite中的群集是一组服务器客户端节点,其中服务器节点以环的形式组合为逻辑结构,并且客户端节点连接到相应的服务器节点。客户端节点和服务器节点之间的主要区别在于,前者不存储数据。







从逻辑的角度来看,数据属于分区,根据某些亲和力函数,这些分区分布在节点之间(有关Ignite中的数据分布的更多信息)。主(primary)分区可以具有副本(备份)。







事务如何在Apache Ignite中工作



Apache Ignite中的集群体系结构对事务处理机制提出了一定要求:分布式环境中的数据一致性。这意味着位于不同节点上的数据必须根据ACID原则进行整体更改有许多协议可用于执行您想要的操作。Apache Ignite使用一个分为两个阶段的两阶段提交算法



  • 准备;
  • 承诺;


请注意,根据事务的隔离级别,获取锁的机制以及许多其他参数,阶段中的详细信息可能会更改。



让我们以下面的事务为例看一下两个阶段如何进行:



Transaction tx = client.transactions().txStart(PESSIMISTIC, READ_COMMITTED);
client.cache(DEFAULT_CACHE_NAME).put(1, 1);
tx.commit();


准备阶段



  1. — (near node Apache Ignite) — prepare- , primary- , .
  2. primary- Prepare- backup-, , . backup- .
  3. backup- Acknowledge- primary-, , , , .




Commit



在从包含主分区的所有节点接收到确认消息后,事务协调器节点发送一个Commit消息,如下图所示。







事务协调器收到所有确认消息后,就认为事务已完成。



从理论到实践



考虑事务的逻辑,让我们转向跟踪。



要在Apache Ignite中启用跟踪,请执行以下步骤:
  • 让我们启用ignite-opencensus模块,并通过集群配置将OpenCensusTracingSpi设置为tracingSpi:

    <bean class="org.apache.ignite.configuration.IgniteConfiguration">
        <property name="tracingSpi">
            <bean class="org.apache.ignite.spi.tracing.opencensus.OpenCensusTracingSpi"/>
        </property>
    </bean>
    


    要么



    IgniteConfiguration cfg = new IgniteConfiguration();
    
    cfg.setTracingSpi(
        new org.apache.ignite.spi.tracing.opencensus.OpenCensusTracingSpi());
    


  • 让我们设置一些非零级别的采样事务:



    JVM_OPTS="-DIGNITE_ENABLE_EXPERIMENTAL_COMMAND=true" ./control.sh --tracing-configuration set --scope TX --sampling-rate 1
    


    要么



    ignite.tracingConfiguration().set(
                new TracingConfigurationCoordinates.Builder(Scope.TX).build(),
                new TracingConfigurationParameters.Builder().
                        withSamplingRate(SAMPLING_RATE_ALWAYS).build());
    


    :



    • API
      JVM_OPTS="-DIGNITE_ENABLE_EXPERIMENTAL_COMMAND=true"
    • sampling-rate , , . , .
    • , SPI, . , , .


  • PESSIMISTIC, SERIALIZABLE .



    Transaction tx = client.transactions().txStart(PESSIMISTIC, SERIALIZABLE);
    client.cache(DEFAULT_CACHE_NAME).put(1, 1);
    tx.commit();




让我们转到GridGain控制中心(该工具的详细概述),然后看一下生成的跨度树: 在图中,我们可以看到在事务()的开头创建的事务根跨度。TxStart调用产生了两个条件跨度组:











  1. 由put()操作启动的锁捕获机:

    1. transactions.near.enlist.write
    2. transactions.colocated.lock.map
  2. transactions.commit, tx.commit(), , , — prepare finish Apache Ignite (finish- commit- ).


现在,让我们仔细看看事务的准备阶段,该阶段从事务协调器节点(在Apache Ignite术语中为近节点)开始,生成transaction.near.prepare span。



进入主分区后,prepare-request会触发transactions.dht.prepare跨度的创建,在该跨度中,prepare-request被发送到tx.process.prepare.req备份,在此由tx.dht.process.prepare.response处理并发送返回到主分区,该主分区沿着创建跨度tx.near.process.prepare.response的方式将确认消息发送到事务协调器。本示例中的“完成”阶段与“准备”阶段相似,这使我们无需进行详细分析。



通过单击任何跨度,我们将看到相应的元信息:







因此,例如,对于根事务跨度,我们看到它是在客户端节点0eefd上创建的。



我们还可以通过启用通信协议的跟踪来增加事务跟踪的粒度。



设置跟踪参数
JVM_OPTS="-DIGNITE_ENABLE_EXPERIMENTAL_COMMAND=true" ./control.sh --tracing-configuration set --scope TX --included-scopes Communication --sampling-rate 1 --included-scopes COMMUNICATION




       ignite.tracingConfiguration().set(
           new TracingConfigurationCoordinates.Builder(Scope.TX).build(),
           new TracingConfigurationParameters.Builder().
               withIncludedScopes(Collections.singleton(Scope.COMMUNICATION)).
               withSamplingRate(SAMPLING_RATE_ALWAYS).build())








现在,我们可以访问有关群集节点之间的网络上消息传输的信息,例如,这将有助于回答是否可能由网络通信的细微差别引起的问题。我们将不讨论细节,我们仅注意socket.write和socket.read跨度的集合分别负责写入套接字和读取此消息或该消息。



异常处理和崩溃恢复



因此,我们看到Apache Ignite中的分布式事务协议的实现接近规范的协议,并允许您根据所选的事务隔离级别来获得适当程度的数据一致性。显然,细节决定了魔鬼,并且上面所分析材料的范围之外还保留了很大的逻辑层。因此,例如,我们没有考虑到参与其中的节点发生故障时交易的操作和恢复机制。我们现在将解决此问题。



上面我们说过,在Apache Ignite中的事务上下文中,可以区分三种类型的节点:



  • 事务协调器(节点附近);
  • 主节点为对应的密钥(primary node);
  • 具有备份密钥分区的节点(备份节点);


以及交易本身的两个阶段:

  • 准备;
  • 完;


通过简单的计算,我们将需要处理节点崩溃的六个选项-从准备阶段的备份下降到完成阶段的事务协调器崩溃。让我们更详细地考虑这些选项。



准备阶段和完成阶段的备份失败



这种情况不需要任何其他操作。作为与主节点重新平衡的一部分,数据将独立地传输到新的备份节点。







准备阶段主节点下降



如果存在接收不一致数据的风险,则事务协调器将引发异常。这是传递控制权以决定重新启动事务的信号,或者是解决客户端应用程序问题的另一种方法。







在完成阶段主节点的掉落



在这种情况下,事务协调器等待其他NodeFailureDetection消息,在接收到该消息后,如果数据已写入备份分区,则事务协调器可以决定事务是否成功完成。







交易协调员倒台



最有趣的情况是事务上下文丢失。在这种情况下,主节点和备用节点直接直接交换本地事务上下文,从而还原全局上下文,这使得可以做出决定来验证提交。例如,如果节点之一报告它未收到完成消息,则事务将回滚。







概要



在以上示例中,我们检查了事务流,并使用跟踪进行了说明,该事务详细显示了内部逻辑。如您所见,Apache Ignite中的事务实现接近两阶段提交的经典概念,在事务性能方面进行了一些调整,涉及到锁定机制,故障后的恢复功能以及事务超时逻辑。



All Articles