Apache Ignite事务架构:2阶段提交协议

本系列文章中,会详细介绍Ignite如何管理键-值API的事务,以及它支持的部分机制和协议,下面是本系列要覆盖的主题:

  • Ignite事务和2阶段提交协议;
  • 并发模型和隔离级别;
  • Ignite持久化层中的事务处理(WAL、检查点及其他);
  • 第三方持久化中的事务处理

在第一篇文章中,我们会先讨论2阶段提交协议(2PC),然后看一下它如何处理各种类型的集群节点。

2阶段提交协议(2PC)

在一个分布式系统中,一个事务可能涉及多个集群节点,很显然,这在确保所有相关节点上的数据一致性方面,面临一些挑战。比如,如果一个节点故障,事务可能在该节点上没有提交。在这个场景中,一个广泛使用的确保一致性的方法就是2阶段提交协议。 顾名思义,它有两个阶段,准备提交,下面看一下细节:

图1:准备阶段

先看一下准备阶段,图1中,有一个示例网络,它由一个客户端(事务发起方),2个主节点和4个备节点组成。 Ignite使用一个分布式哈希表来决定数据在集群中如何分布(分区),集群中中每个主备节点都持有数据的一部分,这些节点会维护一个节点及其拥有的分区的内部分布式哈希表,主备节点只是指向数据所在的位置,主节点就是数据主拷贝所在的位置。如果主节点不可用并且备节点存在的话,数据仍然是可用的。 注意,Ignite没有纯粹的主节点或者备节点,每个节点默认既是主节点,又是备节点,它是一组分区的主节点又是其他分区的备节点。 在图1中,还有一些箭头来显示不同类型节点间的各种消息流:

  1. 客户端发送一个准备消息(1 Prepare)给事务涉及的所有主节点;
  2. 主节点获得所有的锁(取决于事务为悲观还是乐观),然后转发准备消息(2 Prepare)给所有的备节点;
  3. 每个节点会给客户端一个确认(3 ACK, 4 ACK),即所有的锁已经成功获得然后事务准备提交。

图2:提交阶段

下一阶段,会执行提交阶段。在图2中,会看到一个类似于准备阶段的消息流:

  1. 客户端发送提交消息(5 Commit)给事务涉及的所有主节点;
  2. 主节点提交事务并且转发提交消息(6 Commit)给所有的备节点,然后备节点提交事务;
  3. 每个节点返回事务提交成功的确认消息给客户端(7 ACK, 8 ACK)。

这里可能发生许多故障,比如备节点故障,主节点故障,或者甚至客户端故障,我们后续会研究这些场景,然后在其它文章中介绍Ignite如何进行应对。

节点类型

前面的讨论中提到了集群节点的各种类型,客户端节点(事务发起方)在Ignite社区中通常称为近端节点,而其它节点成为远端节点,如图3所示:

图3:节点类型

通常来说,应用会通过客户端节点接入集群,应用和客户端节点的职责分工如下:

  1. 应用调用方法:
  • txStart()
  • cache.put()
  • cache.get()
  • tx.commit()
  1. 客户端节点管理其他的操作:
  • 事务初始化
  • 事务状态跟踪
  • 发送准备和提交消息
  • 协调整个事务过程

下面是Ignite文档中的一小段示例代码,显示了事务的执行方式:

try (Transaction tx = transactions.txStart()) {

    Integer hello = cache.get("Hello");
  
    if (hello == 1)
        cache.put("Hello", 11);
  
    cache.put("World", 22);
  
    tx.commit();
}

本例中会看到,可以通过txStart()方法开始事务,可以通过tx.commit()方法提交事务。相应的,在try块体中,代码在Hello键上执行了一个**cache.get()操作,然后,然后判断值是否为1,如果是,那么通过cache.put()将值改为11,然后通过cache.put()**在缓存中写入另一个键-值对。

总结

在第一篇文章中,快速地预览了2阶段提交协议,然后描述了Ignite的处理方式,在本系列的下一部分中,会看到乐观和悲观锁模型还有隔离级别。

本文译自GridGain的技术布道师Akmal B. Chaudhri的博客

猜你喜欢

转载自my.oschina.net/liyuj/blog/1626309