作者介绍:Redfox。

原文链接:Ignite Transaction

1. Atomicity Mode

Ignite的支持跨cache的transaction,跨cache的transaction时要求不同cache之间的Atomicity Mode是相同的。
Cache的Atomicity Mode通过CacheConfiguration中的atomicityMode进行配置,主要支持下面三种Atomicity Mode:

TRANSACTIONAL_SNAPSHOT

  • 支持多个操作的多个key放在一个逻辑操作(事务)中,放在一个逻辑操作中的事务要么全成功,要么全失败,支持ACID特性

  • 同时支持K/V事务和SQL事务,使用MVCC来支持两种类型的事务

  • 不支持near cache

TRANSACTIONAL

  • 支持多个操作的多个key放在一个逻辑操作(事务)中,放在一个逻辑操作中的事务要么全成功,要么全失败,支持ACID特性

  • 支持K/V事务

  • 支持near cache

ATOMIC

  • 所有的操作都是原子的,一次同时只执行一个操作

  • 因为不用去做事务锁,所以性能比TRANSACTIONAL、TRANSACTIONAL_SNAPSHOT要高

  • 批量写入(例如PutAll、RemoveAll)可能会部分成功部分失败,这个操作会抛出一个异常,异常中间包含没有写入成功的K/V

2. Concurrency & Isolation

Concurrency:Ignite支持乐观并发控制模式和悲观并发控制模式,选择什么样的并发控制模式决定了在什么时机对entry进行加锁操作。悲观并发控制模式是在prepare阶段就对事务所操作的entry进行加锁,乐观并发控制模式是在访问数据的时候,就对entry进行加锁。无论选择哪种并发控制模式,在事务commit之前都存在一个时间区间,在这个区间内,事务所操作的所有entry,都是加锁状态的。

Isolation:隔离级别定义了并发执行的事务,对同时操作的key,是如何看待和如何处理的。Ignite支持READ_COMMITED、REPEATABLE_READ、SERIALIZABLE几种隔离级别。

所以并发控制模型和隔离级别是一个事务的两个方面,下面是ignite在这两个方面的支持。

2.1 悲观事务

悲观事务在事务执行第一条读取或者写入(根据隔离级别来看是第一条读取还是写入)的时候,就会对事务中所有的entry进行加锁,直到事务commit或者rollback才释放锁定。在这个模式下,锁定首先在primary节点上进行,在prepare阶段将锁定推送到backup节点上去,悲观事务的加锁顺序很重要(避免死锁)。ignite中会对entry按照约定的顺序规则进行加锁,悲观事务下支持的隔离级别如下:

READ_COMMITED
数据读取的时候不进行加锁,也不需要将数据读取到transaction中进行缓存,在第一次写入的时候才对所有的entry加锁。如果cache配置中允许的话,可以在backup节点上读取数据。READ_COMMITED可能的问题就是会导致不可重复读,即在一个事务中读取两次数据,可能会结果不一样。

REPEATABLE_READ
在第一次读写数据时,就将数据从primary节点读取到transaction map中,并且对所有的entry进行加锁。所有在这个事务中后续对同一份数据的读取,都可以读到在这个事务里面更新的最新数据,其它并发事务不能修改这个事务里的数据,所以可以获得可重复读。

SERIALIZABLE
和REPEATABLE_READ的工作方式相同。

悲观事务下的注意点

性能:因为悲观事务需要对所有的entry提前加锁,而且加锁是要按照一定的顺序控制的。所以,类似于putAll这种操作,如果将顺序相同的key放到一个part上进行操作,可能会减少在客户端与服务端之间加锁的锁定往来次数;

Long Transaction:因为在悲观事务下,我们不能修改集群的topology,要尽量减少时间比较长的悲观事务;

读取的一致性:只有在REPEATABLE_READ和SERIALIZABLE的隔离级别下,才能保证完整的读取一致性,通过读锁避免事务在过程中更新。

2.2 乐观事务

乐观事务在两阶段提交的prepare阶段才在primary节点上对entry进行加锁,加锁之后提交到backup节点上,在commit阶段释放所拥有的锁。

READ_COMMITED
在cache中的数据修改是在发起节点上先收集所有的更改,然后在事务commit阶段进行应用,数据读取的时候不进行加锁,也不需要将数据读取到transaction中进行缓存。如果cache配置中允许的话,可以在backup节点上读取数据,READ_COMMITED可能的问题就是会导致不可重复读,即在一个事务中读取两次数据,可能会结果不一样。

REPEATABLE_READ
和READ_COMMITED的实现方式相同,区别在于REPEATABLE_READ会把所有的读取过来的数据在发起节点上进行缓存,这样所有后续这个事务操作的读取,都可以确保是local的。

SERIALIZABLE
在第一次读取某个entry的时候,保存这个entry的版本号。如果在事务commit的时候,发现这个事务操作的所有entry存在一个entry的版本号和集群当前最新的entry版本号不相同,则这个事务失败,并对这个事务的修改操作进行回滚,用户需要处理这个异常,并且重试这个事务。这个中间需要特别强调的是即使这个事务只有读操作,没有写操作,这个事务也可能失败(假设后面读取的数据和事务刚开始时的数据不相同)。

乐观事务下的注意点

SERIALIZABLE下的重试:因为乐观事务是在操作过程中发现不能操作时,返回和抛出异常。所以我们需要捕获这种异常,然后进行重试,可能导致多个乐观事务循环重试的状态,所以我们在加锁时,也要考虑对entry加锁的顺序,降低循环重试的可能性;

读取一致性:只有在SERIALIZABLE的情况下,才能保证读取的一致性。但是即使在SERIALIZABLE的隔离级别下,在COMMIT之前,都可能发生部分读的现象,所以一定需要去捕获抛出的异常,以确保读取是一致的。

3. MVCC

只有TRANSACTIONAL_SNAPSHOT的原子模式,才支持MVCC特征,这个模式同时支持SQL事务和K/V事务,这两种类型的事务都支持MVCC。

MVCC是数据被多个用户并发访问时候,控制数据一致性的方法。每个事务在启动时获得数据的一致性快照,这个事务后续的操作只能看到和修改这个快照内的数据。当事务更新一个entry时,它需要确保这个entry没有被其它事务更新,然后创建这个entry的一个新的版本。这个新版本只有在这个事务commit之后才能被其它事务可见,如果这个entry被更新了,那么这个事务就会失败。Snapshot并不是物理的,而是逻辑的。它是由集群中的某个节点进行管理这些活动事务(MVCC-coordinator),这个节点追踪所有的活动事务,并且在每个事务结束时,都会通知到该节点。所有打开MVCC的cache操作,都需要从这个节点上获得快照数据。

目前TRANSACTIONAL_SNAPSHOT只支持悲观事务和REPEATABLE_READ隔离级别。

并发更新

当在一个事务里面(事务A),先读取一个entry,再更新这个entry过程中,可能存在另外一个事务在两个操作中间将这个entry更新的情况发生,如果这种情况发生,那么事务A会被置为“rollback only”(只允许回滚)的状态,ignite会抛出异常和设置SQL的状态码,让用户来处理这种状态,通常这个事务就需要重试。

限制

跨cache事务
在同一个事务里面要求所有的cache都设置为TRANSACTIONAL_SNAPSHOT模式,因此,如果需要在一个SQL事务中操作多个table,那么所有的table创建时,也要配置为TRANSACTIONAL_SNAPSHOT模式

嵌套事务
Ignite支持3种方案来处理嵌套事务,方案在JDBC、ODBC的连接参数中配置。

ERROR方案:当碰到嵌套事务,则抛出错误,同时外面的事务进行回滚,默认采用这种方案;

COMMIT方案:外围事务进行提交,嵌套事务在碰到COMMIT语句时进行提交,外围事务剩下的语句采用隐含事务模式;

IGNORE: 嵌套事务的BEGIN语句被忽略,嵌套事务中的语句被和外围事务一样执行,碰到COMMIT之后,进行事务提交,外围事务剩余的语句采用隐含事务模式。

持续查询
如果有其它操作在更新数据,那么持续查询获得的结果可能是过期的数据,因为更新数据需要时间通知到MVCC-coordinator节点上;

一个事务同时更新的记录数会被限制,因为可能造成内存泄漏,默认限制为20000条;

MVCC模式不支持:near cache、超时策略、事件通知、cache解析器、第三方持久化、堆内cache。

4. Two Phase Commit


两阶段提交

在分布式的ignite中,一个事务中的操作可能牵涉到修改多个partition上的数据,一个partition里面也存在主节点和备份节点,要保持一个事务中对所有节点的数据修改是一致的。ignite采用两阶段提交的方案来进行事务操作,两阶段提交事务中存在3个角色:
事务协调者(Transaction Coordinator):事务发起节点,它来控制事务的两阶段提交过程。
主节点(Primary Partition):ignite中某个partition的主节点,数据读写操作的主要对象。
备份节点(Backup Partition):ignite中某个partition数据备份的所在节点。

5. Near Node & Remote Node

在ignite中,Transactional coordinator也被称为Near Node。Near Node控制整个事务操作的全部流程,包括发起事务、跟踪事务状态、发起prepare、发起commit以及等待事务完成。

Near Node通常是也是集群的client节点。

6. Transaction Lifecycle

在ignite中,事务由tx.start()发起,然后在Near Node上创建Transaction的上下文环境,同时在Near Node上还要做以下事情:
1)为Transaction分配一个事务ID;
2)记录Transaction开始的时间;
3)记录当前topology的version、状态和信息。

将Transaction设置为active状态,然后执行读写操作,再执行Commit操作,完成事务。Transaction commit之后,开始执行两阶段提交,在prepare阶段,primary完成时需要做做以下事情:
1)检查保存在Transaction上下文中的topology version和当前的topology version是否相同;
2)获得所有的锁;
3)创建一个DHT上下文,保存所有的数据;
4)等待或者跳过备份节点完成prepare;
5)Near Node发起执行commit操作;
6)等待所有节点完成commit操作。

7. Pessimistic & READ_COMMITED

在这种组合模式下,读取数据(例如get、getAll等操作),是不会对entry进行加锁的。所以,可能存在刚开始读到的某个entry的数据,和事务完成(commit)时读到的某个entry的数据是不相同的。

在收到对某个entry的修改操作时,会对这个entry进行锁定操作。当发起commit之前,事务已经完成对所有该事务需要修改的数据的锁定,commit时,才会对primary或者backup上的二数据发起真正的修改操作。

锁的释放只有在整个事务完成之后才进行释放。

8. Pessimistic & (SERIALIZABLE | REPEATABLE_READ)

在这两种组合模式下,Near Node发现读取数据(例如get、getAll等操作)时,就会对读取的数据进行加锁操作,同样的数据修改操作也会对读取的数据进行加锁操作。

锁的释放只有在整个事务完成之后才进行释放。

9. Optimistic & (READ_COMMITED|REPEATABLE_READ)

在这两种并发控制组合模式下,数据锁定在prepare阶段才会发生(事务的commit,两阶段提交的prepare),相对于悲观并发控制模式(Near Node上发现有读写即进行锁定)来说,延后了对entry的锁定时间。在prepare阶段,不会比较entry的版本号。

10. Optimistic & SERIALIZABLE

在这两种并发控制组合模式下,数据锁定在prepare阶段才会发生(事务的commit,两阶段提交的prepare),相对于悲观并发控制模式(Near Node上发现有读写即进行锁定)来说,延后了对entry的锁定时间。在prepare阶段,会比较entry的版本号,与事务刚开始时的entry版本号。如果在prepare阶段发现版本号与事务刚开始时的版本号不相同,那么在prepare阶段就失败。

11. Lock Timeout

Ignite允许设置一个事务的超时时间,在这种设定模式下,当事务的执行事件超过约定的超时时间时,事务执行失败,需要进行rollback

悲观并发控制模式下:每次对entry进行锁定,都会比较事务执行是否超时

乐观并发控制模式下:只有在prepare阶段进行锁定时,才比较事务执行是否超时

所有参与事务的节点都会检查超时。如果超时,那么会在事务中设计一个标记,以方便NearNode执行事务撤销(回滚操作)

12. Backup Node Failure

如果一个backup节点损坏,那么事务仍旧会在剩余的节点上完成执行,不会对当前事务的执行产生任何影响。

在事务执行完后,会为这个partition选择一个新的backup节点。

13. Primary Node Failure On Prepare

如果primary节点在prepare阶段失效,那么系统会抛出一个异常给到客户端,客户端再将异常给到应用程序,由应用程序来决定是重新执行该事务还是做其它工作。

14. Primary Node Failure On Commit

如果primary节点在prepare节点完成之后失效,那么Near Node会等待backup节点发送过来的消息。

Backup节点发现primary节点失效情况下,会发送消息给到NearNode节点。如果backup已经完成了这个事务需要完成的所有修改操作,则Near Node会继续完成这个事务。

同时topology开始发生改变,并选择一个新的primary来代替失效的primary。

15. Coordinator(Near Node) Failure

如果Near Node失效,那么处理过程会比较复杂,因为系统中可能有的节点已经完成了commit,有的节点还没有完成commit,而且系统中的transaction的状态目前是没有保存的。

系统中的primary节点互相交换信息,只要有一个primary节点没有完成commit,则触发对这个transaction的回滚操作,参与这个事务的所有节点进行回滚。

MemFireDB,带你体验不一样的云端飞翔。

Ignite Transaction相关推荐

  1. Ignite 数据网格快速学习(一)

    PS:所有的代码使用的是Ignite2.0 #1.数据的基本存储操作 public static void main(String[] args) {//Ignition.start(...)启动一个 ...

  2. java.lang.IllegalStateException: Cannot modify managed objects outside of a write transaction. in /U

    错误内容如下 java.lang.IllegalStateException: Cannot modify managed objects outside of a write transaction ...

  3. redis 在 php 中的应用(事务 [ Transaction ] 篇)

    本文为我阅读了 redis参考手册 之后编写,注意 php_redis 和 redis-cli 的区别(主要是返回值类型和参数用法) 目录: Transaction(事务) WATCH UNWATCH ...

  4. 用Apache Ignite实现可扩展的数据网格

    在本文中,我们将先介绍数据网格(Data Grid)的基本概念.属性.以及能够提供的服务,然后讨论如何设计可扩展的数据网格,以满足实际场景的业务需求. 什么是数据网格? 数据网格是一组能够提供共享数据 ...

  5. Oracle Block浅析2:ITL(Interested Transaction List)

    一.ITL(Interested Transaction List): ITL(Interested Transaction List)是Oracle数据块内部的一个组成部分,位于数据块头(block ...

  6. Fragment提交transaction导致state loss异常

    下面自从Honeycomb发布后,下面栈跟踪信息和异常信息已经困扰了StackOverFlow很久了. java.lang.IllegalStateException: Can not perform ...

  7. sql server 2005 T-SQL BEGIN TRANSACTION (Transact-SQL)

    标记一个显式本地事务的起始点.BEGIN TRANSACTION 使 @@TRANCOUNT 按 1 递增. Transact-SQL 语法约定 语法 BEGIN { TRAN | TRANSACTI ...

  8. 炸裂!微软重磅推出混合现实平台 Mesh、基于 Excel 的低代码语言 Power Fx,Ignite 2021 太精彩!...

    作者 | 伍杏玲 出品 | CSDN(ID:CSDNnews) "一开始,这就是混合现实的梦想." 在微软 Ignite 2021 大会上,微软 HoloLens 之父 Alex ...

  9. mysql中transaction的实现

    transaction在数据库编程中是一个重要的概念,这样做可以控制对数据库操作的事务提交. 但是要想在程序中实现事务,要求数据库本身支持事务. 现在的关系型数据库,我们日常使用的mysql,orac ...

最新文章

  1. Android在屏幕任意位置显示对话框
  2. MyEclipse开发教程:使用REST Web Services管理JPA实体(四)
  3. c语言用什么能暂存结构指针,c语言中什么是指针
  4. 如果硬盘不显示可以这么处理
  5. MySQL 集群方案介绍
  6. 架构师一般做到多少岁_软件测试可以做到多大岁数?
  7. jq获取id的名称_查找 Linux 发行版名称、版本和内核详细信息 | Linux 中国
  8. MySQL性能优化的参数简介
  9. 用HQL进行实体查询
  10. Wireshark软件使用教程
  11. Python自制成语接龙小游戏
  12. 拍拍抢拍精灵v2.1秒杀器所有源代码【开源】
  13. 知网文献nh、caj格式文件转成pdf
  14. 欧几里德结构数据(Euclidean Structure Data) 以及非欧几里德结构数据(Non-Euclidean Structure Data)
  15. SkeyePlayer源码解析系列之支持H265
  16. Google巧妙发布Sky星空地图
  17. 贝尔宾九种团队角色理论总结(转)
  18. 用友uap开发报错:流程平台缓存中不存在该单据或交易类型=xxx
  19. 利用kiftd实现局域网文件共享,支持不同操作系统
  20. 科达视频会议助力宁波鹰星针纺

热门文章

  1. K2+微软平台集成解决方案在线研讨会
  2. deepin linux VScode 设置启动命令 code
  3. dxperience 10.1.4 下载 汉化 破解
  4. 计算机技术在心理学研究应用,面向心理学领域的计算机技术的应用
  5. 关注欧洲杯(1)之:老梁说欧洲杯抽签
  6. 令狐冲独孤九剑篇--策略模式
  7. 毕升Office安装
  8. 【调剂】浙大城市学院2023年硕士研究生招生调剂公告
  9. 【大二 电子信息工程】
  10. 关于@(posedge clk)和@(itf.cb)的区别