这段内容讲的是 Apache Ignite 中事务的使用方式和机制,包括如何启用事务、执行事务、并发模式(Concurrency Mode)和隔离级别(Isolation Level)等。下面我用中文详细解释这段内容,帮助你更好地理解。
一、事务概述(Overview)
1. 启用事务支持
要在一个缓存中使用事务,必须在配置中将缓存的 原子性模式(atomicityMode) 设置为 TRANSACTIONAL
。
CacheConfiguration<Integer, String> cfg = new CacheConfiguration<>("myCache");
cfg.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL);
- 只有设置为
TRANSACTIONAL
模式后,缓存才支持事务操作。 - 如果设置为
ATOMIC
(默认),则不支持事务。
🔍 参考:
Atomicity Mode(原子性模式)
决定了缓存是支持原子操作(ATOMIC)还是事务操作(TRANSACTIONAL)。
二、事务的执行(Executing Transactions)
Ignite 提供了基于 Key-Value API 的事务接口,可以让你手动控制事务的开始、提交和回滚。
示例代码:
Ignite ignite = Ignition.ignite();
IgniteCache<String, Integer> cache = ignite.cache("myCache");
IgniteTransactions transactions = ignite.transactions();
try (Transaction tx = transactions.txStart()) {
Integer hello = cache.get("Hello");
if (hello == 1)
cache.put("Hello", 11);
cache.put("World", 22);
tx.commit(); // 提交事务
}
说明:
- 使用
transactions.txStart()
启动一个事务。 - 所有在事务中的操作(如
get
、put
)都会被当作一个整体。 - 最后调用
tx.commit()
提交事务。如果发生异常,可以调用tx.rollback()
回滚。 - 事务是 原子性的:要么全部成功,要么全部失败,不会出现部分更新。
三、并发模式(Concurrency Modes)
事务支持两种并发模式:
并发模式 | 描述 |
---|---|
OPTIMISTIC(乐观) | 在事务提交时检查是否有冲突。适用于并发冲突较少的场景。 |
PESSIMISTIC(悲观) | 在事务访问数据时立即加锁,防止其他事务修改。适用于并发冲突较多的场景。 |
锁的获取时机:
- OPTIMISTIC:在事务提交时检查冲突,不提前加锁。
- PESSIMISTIC:在事务访问数据时就加锁,直到事务提交或回滚才释放。
⚠️ 注意: 如果使用 PESSIMISTIC 模式,事务会锁定相关数据,可能会影响拓扑变更(如添加/删除节点、销毁缓存等),详见之前的“拓扑变更限制”内容。
四、隔离级别(Isolation Levels)
隔离级别决定了多个事务之间如何相互“看到”彼此的操作。
Ignite 支持以下三种隔离级别:
隔离级别 | 描述 |
---|---|
READ_COMMITTED | 事务只能读取已经提交的数据。防止脏读。 |
REPEATABLE_READ | 事务在执行期间多次读取同一数据,结果保持一致。防止脏读和不可重复读。 |
SERIALIZABLE | 最严格的隔离级别。事务串行执行,防止脏读、不可重复读和幻读。 |
举例说明:
- READ_COMMITTED:你读到的数据一定是其他事务已经提交的。
- REPEATABLE_READ:你在事务中两次读同一个 key,结果是一样的。
- SERIALIZABLE:所有事务串行执行,不会有并发问题,但性能最低。
五、并发模式 + 隔离级别的组合
Ignite 支持所有并发模式和隔离级别的组合,每种组合有不同的行为和一致性保证。
并发模式 | 隔离级别 | 行为特点 |
---|---|---|
OPTIMISTIC | READ_COMMITTED | 提交时检查冲突,只允许读已提交的数据 |
OPTIMISTIC | REPEATABLE_READ | 提交时检查冲突,保证事务中多次读相同数据一致 |
OPTIMISTIC | SERIALIZABLE | 提交时检查冲突,事务串行化执行 |
PESSIMISTIC | READ_COMMITTED | 访问数据时加锁,只允许读已提交的数据 |
PESSIMISTIC | REPEATABLE_READ | 访问数据时加锁,保证多次读相同数据一致 |
PESSIMISTIC | SERIALIZABLE | 访问数据时加锁,事务串行执行 |
六、事务配置(Transaction Configuration)
你可以在 IgniteConfiguration
中对事务进行一些全局配置,比如设置事务超时时间:
<bean class="org.apache.ignite.configuration.IgniteConfiguration">
<property name="transactionConfiguration">
<bean class="org.apache.ignite.configuration.TransactionConfiguration">
<!-- 设置事务在拓扑变更时的最大等待时间为20秒 -->
<property name="txTimeoutOnPartitionMapExchange" value="20000"/>
</bean>
</property>
</bean>
这个配置用于控制事务在分区映射交换(Partition Map Exchange)期间等待的最长时间。
七、总结表格
概念 | 说明 |
---|---|
原子性模式 | 设置为 TRANSACTIONAL 才能使用事务 |
事务执行 | 使用 txStart() 开启事务,commit() 提交,rollback() 回滚 |
并发模式 | OPTIMISTIC(乐观)和 PESSIMISTIC(悲观) |
隔离级别 | READ_COMMITTED、REPEATABLE_READ、SERIALIZABLE |
锁机制 | PESSIMISTIC 会立即加锁,OPTIMISTIC 在提交时检查冲突 |
拓扑限制 | PESSIMISTIC 事务期间不能修改缓存拓扑 |
配置 | 可设置事务超时时间等参数 |
✅ 建议做法:
- 尽量避免长时间持有事务,尤其是 PESSIMISTIC 模式。
- 如果并发冲突少,可以使用 OPTIMISTIC + READ_COMMITTED,性能更好。
- 如果数据一致性要求高,可以使用 PESSIMISTIC + REPEATABLE_READ。
- 事务中尽量减少操作的数据量和时间,避免影响集群拓扑变更。
如果你在开发中需要保证多个缓存操作的原子性和一致性,Ignite 的事务机制是一个非常有用的工具。理解并发模式和隔离级别的区别,有助于你根据业务需求选择合适的事务配置。