Apache-Ignite入門實(shí)戰(zhàn)之二 - 事務(wù)處理

前一篇文章介紹了怎樣安裝和使用 Ignite 的緩存。今天說說 Ignite 的緩存事務(wù)。

在我們平時(shí)的開發(fā)中經(jīng)常會(huì)有這么一種場(chǎng)景,兩個(gè)或多個(gè)線程同時(shí)在操作一個(gè)緩存的數(shù)據(jù),此時(shí)我們希望要么這一批操作都成功,要么都失敗。這種場(chǎng)景在數(shù)關(guān)系型據(jù)庫中很常見,就是通過數(shù)據(jù)庫的事務(wù)處理來實(shí)現(xiàn)的。下面我們就看看 Ignite 怎樣實(shí)現(xiàn)這種事務(wù)處理。

下面先看一個(gè)測(cè)試程序。

package my.ignitestudy.datagrid;

import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.Ignition;
import org.apache.ignite.cache.CacheAtomicityMode;
import org.apache.ignite.configuration.AtomicConfiguration;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
import org.apache.ignite.transactions.Transaction;
import org.apache.ignite.transactions.TransactionConcurrency;
import org.apache.ignite.transactions.TransactionIsolation;

import java.util.Arrays;

public class TransactionExample {
    public static void main( String[] args ) throws Exception {
        TestTransaction();
    }

    private static Ignite getIgnite() {
        TcpDiscoverySpi spi = new TcpDiscoverySpi();
        TcpDiscoveryVmIpFinder ipFinder = new TcpDiscoveryVmIpFinder();
        ipFinder.setAddresses(Arrays.asList("192.168.0.192:47500..47509"));
        spi.setIpFinder(ipFinder);
        IgniteConfiguration cfg = new IgniteConfiguration();
        cfg.setDiscoverySpi(spi);
        cfg.setClientMode(true);

        Ignite ignite = Ignition.start(cfg);
        return ignite;
    }

    private static void TestTransaction() throws Exception {
        final Ignite ignite = getIgnite();
        CacheConfiguration cacheCfg = new CacheConfiguration();
        cacheCfg.setName("default");
        cacheCfg.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL);
        cacheCfg.setBackups(1);
        final IgniteCache<String, String> cache = ignite.getOrCreateCache(cacheCfg);

        cache.remove("MyKey");

        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Transaction 1: begin");
                try (Transaction tx = Ignition.ignite().transactions().txStart(TransactionConcurrency.OPTIMISTIC, TransactionIsolation.SERIALIZABLE)) {
                    String value = cache.get("MyKey");

                    cache.put("MyKey", "MyValue 1");
                    try {
                        Thread.currentThread().sleep(5 * 1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println("Transaction 1: before commit, " + cache.get("MyKey"));
                    tx.commit();
                    System.out.println("Transaction 1: after commit, " + cache.get("MyKey"));
                }

                System.out.println("Transaction 1: end");
            }
        }).start();

        Thread.currentThread().sleep(2 * 1000);

        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Transaction 2: begin");
                try (Transaction tx = Ignition.ignite().transactions().txStart(TransactionConcurrency.OPTIMISTIC, TransactionIsolation.SERIALIZABLE)) {
                    String value = cache.get("MyKey");

                    cache.put("MyKey", "MyValue 2");

                    System.out.println("Transaction 2: before commit, " + cache.get("MyKey"));
                    tx.commit();
                    System.out.println("Transaction 2: after commit, " + cache.get("MyKey"));
                }
                System.out.println("Transaction 2: end");
            }
        }).start();
    }
}
  • 測(cè)試程序中使用兩個(gè)線程同時(shí)操作一塊緩存。并且第二個(gè)線程稍晚運(yùn)行,目的是為了等待第一個(gè)線程先把數(shù)據(jù)修改了,這是為了比較容易測(cè)試我們的程序。
  • 要使用 Ignite 事務(wù),需要將原子模式配置成 “CacheAtomicityMode.TRANSACTIONAL”,此配置也可以子啊配置文件里指定。
    cacheCfg.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL);
    
- 通過使用 Ignition.ignite().transactions().txStart(TransactionConcurrency, TransactionIsolation) 來創(chuàng)建事務(wù)。其中事務(wù)并發(fā)模式 TransactionConcurrency 可以是 OPTIMISTIC 或 PESSIMISTIC。 事務(wù)級(jí)別 TransactionIsolation 可以是 READ-COMMITTED,REPEATABLE_READ 和 SERIALIZABLE。
- 在我們開發(fā)使用事務(wù)的場(chǎng)景下,我們可以通過調(diào)整事務(wù)并發(fā)模式和事務(wù)級(jí)別參數(shù)來滿足我們不同業(yè)務(wù)的需要。
- 事務(wù)最后需要使用 commit() 來提交修改,或通過 rollback() 來回滾修改。

運(yùn)行測(cè)試程序,可以看到第一個(gè)線程修改了緩存,但是并沒有提交修改,而是等到第二個(gè)線程提交修改后,此時(shí)第一個(gè)線程就會(huì)拋出異常,rollback修改。


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容