Search code examples
c#ignite

Apache.Ignite.Net CacheStoreFactory and CacheMode.Replicated does not write to all nodes


Working with C#, Apache Ignite 2.4 on Windows 10, I aim to have multiple, replicated nodes with each a custom CacheStoreFactory. I like every node's CacheStoreFactory to be called whenever a cache entry changes. The following code sample results in an output to what I had expected to be the behaviour of CacheMode.Partitioned. With CacheMode.Replicated I'd expect two output lines (because two nodes are running) for every cache.Put operation. How can I achieve this?

Output

Node count: 2
Started..
Write 0-0 by 63642613
Write 1-1 by 12036987
Write 2-2 by 63642613
Write 3-3 by 12036987
Write 4-4 by 63642613
Write 5-5 by 63642613
Write 6-6 by 12036987
Write 7-7 by 63642613
Write 8-8 by 12036987
Write 9-9 by 12036987
Finished count1:10 count2:10

Sample code

class Program
{
    static void Main(string[] args)
    {
        var config = new IgniteConfiguration()
        {
            IgniteInstanceName = "A",
            CacheConfiguration = new List<CacheConfiguration>
            {
                new CacheConfiguration("mycache",new QueryEntity(typeof(int), typeof(int)))
                {
                    CacheMode = CacheMode.Replicated,
                    WriteThrough = true,
                    CacheStoreFactory = new StoreFactory(),
                },
            },
        };

        var ignite1 = Ignition.Start(config);
        config.IgniteInstanceName = "B";
        var ignite2 = Ignition.Start(config);

        Console.WriteLine("Node count: " + ignite1.GetCluster().GetNodes().Count);
        ignite1.GetCluster().SetActive(true);

        var mycache1 = ignite1.GetCache<int, int>("mycache");
        var mycache2 = ignite2.GetCache<int, int>("mycache");
        Console.WriteLine("Started..");
        for (int i = 0; i < 10; i++)
        {
            mycache1.Put(i, i);
        }
        Console.WriteLine($"Finished count1:{mycache1.Count()} count2:{mycache2.Count()}");
        Console.ReadLine();

        ignite1.Dispose();
        ignite2.Dispose();
    }

    private class StoreFactory : IFactory<ICacheStore>
    {
        public ICacheStore CreateInstance() { return new Store(); }
    }

    private class Store : CacheStoreAdapter<int, int>
    {
        public override void Delete(int key) { }

        public override int Load(int key) { return 1; }

        public override void Write(int key, int val)
        {
            Console.WriteLine($"Write {key}-{val} by {this.GetHashCode()}");
        }
    }
}

Solution

  • Each key has its own primary node even with Replicated cache and only this primary node will write the value to the store. Ignite expects that all nodes will have the same underlying CacheStore and in this case, it makes sense to write the value to it only once since there is no need to write it again from backup.

    If you want to have distributed underlying store, I'd recommend to try Ignite Native Persistence: https://apacheignite.readme.io/docs/distributed-persistent-store