1
votes

I'm working on an application using an Ignite.Net cache infront of an Oracle database.

I read that I can write to multiple caches at once safely using Ignite Transactions (https://apacheignite-net.readme.io/v1.5/docs/transactions#Cross-cache transactions).

I also read that each cache can have it's own CacheStore that writes to the underlying database but I've yet to find any documentation that explains how I should implement the CacheStore classes so the database writes are safe across the whole Ignite transaction.

I've seen information on SessionEnd and CacheStoreSession (https://apacheignite-net.readme.io/v2.6/docs/persistent-store#section-sessionend-) but these don't mention multiple CacheStores.

The following article explains how transactions are handled for 3rd party persistence but this again only talks of a single Cache/CacheStore (https://www.gridgain.com/resources/blog/apache-ignite-transactions-architecture-transaction-handling-level-3rd-party) Can anyone advise how this works (assuming it does) or point me to further examples/documentation?

2
Do different cache stores write to different databases, or to a single one? - Valentin Kulichenko
To a single database - IAmConfused

2 Answers

2
votes

For a definitive answer (appreciate your time @alamar), I've spoken with one of the nice people at Gridgain and can confirm it is possible to safely perform transactions across multiple CacheStores, where all stores write to the same database without data inconsistency. It's not done via a mechanism specifically coded into Ignite as I had wondered about but can be implemented safely via a simple shared database connection.

For this to work you need to:

  1. Make your caches transactional (AtomicityMode = CacheAtomicityMode.Transactional, WriteThrough = true)
  2. Share a single database connection between the data stores (either inject via the CacheStoreFactory or use a singleton)
  3. In all write operations on the CacheStores, write to the shared session database but do not commit. Mark the session as requiring a commit (your own boolean flag).
  4. Implement SessionEnd (https://apacheignite-net.readme.io/docs/persistent-store#section-sessionend-) in each of your CacheStores. The implementation should call commit on your shared database connection if it has not already been called (check the boolean flag from the step before and reset after commit). You could always encapsulate that logic in your database connection class.

A simplified code example:

public class SharedDatabaseSession
{
    private bool commitRequired;
    private DatabaseConnection databaseConnection;

    // ....

    public void Write( /*xyz*/)
    {            
        databaseConnection.Write( /*xyz*/);
        commitRequired = true;
    }

    public void Commit()
    {
        if (commitRequired)
        {
            databaseConnection.Commit();
            commitRequired = false;
        }
    }

    public static SharedDatabaseSession GetInstance()
    {
        return instance;
    }
}

public class FirstCacheStore : CacheStoreAdapter<int, int>
{
    private SharedDatabaseSession database = SharedDatabaseSession.GetInstance();

    /// ...... 

    public override void Write(int key, int val)
    {
        database.Write( /*xyz*/);
    }

    public override void SessionEnd(bool commit)
    {
        if (commit)
        {
            database.Commit();
        }
    }
}

public class SecondCacheStore : CacheStoreAdapter<int, int>
{
    private SharedDatabaseSession database = SharedDatabaseSession.GetInstance();

    /// ...... 

    public override void Write(int key, int val)
    {
        database.Write( /*xyz*/);
    }

    public override void SessionEnd(bool commit)
    {
        if (commit)
        {
            database.Commit();
        }
    }
}
1
votes

Have you tried it?

My expectation, it should technically be supported, but since Cache Store uses two phase commit, and multiple Cache Stores will need to use "three phase commit", and there's no such thing - that you can expect data inconsistency on edge cases.

Happy path should, however, work OK.