Cookie Consent by Free Privacy Policy Generator Distributed Data Structures - NCache

Distributed Data Structures in NCache

NCache is an extremely fast and scalable Distributed Cache for .NET, Java, Node.js, and Python applications. NCache is used by high-transaction .NET server applications for application data caching, ASP.NET / ASP.NET Core session storage, and Pub/Sub Messaging.

NCache offers Distributed Data Structures that can be shared among multiple users. Unlike local structures that reside in the client application's heap, these structures are hosted in the Distributed Cache Cluster, reducing local memory pressure and garbage collection overhead. These include:

Feature Standard In-Process Collections NCache Distributed Structures
Scope Process-Bound (Local Heap) Cluster-Wide (Shared Network Resource)
Lifecycle Lost on Application Restart/Recycle Independent of Application Lifecycle
Availability Single Point of Failure (The Process) High Availability (via Partition/Replica topologies)
Consistency Thread-Safe only within single process Guaranteed Consistency across multiple servers

The following sections provide details and code examples for .NET and Java applications.

 

Distributed Queue

A Distributed Queue implements the IDistributedQueue<T> interface, allowing you to create a Queue to be shared among multiple .NET and Java applications running in a distributed environment. And, the Queue ensures that the sequence in which you’ve entered data in it is maintained. All applications retrieving data from the Queue can rely on this sequence always being correct.

string cacheName = "demoCache";
string QueueName = "DistributedQueue:Customers";
  
// Initialize an instance of the cache to begin performing operations
ICache cache = CacheManager.GetCache(cacheName);
  
// Create a thread-safe distributed queue visible to all cluster nodes
IDistributedQueue<Customer> distQueue = 
cache.DataTypeManager.CreateQueue<Customer>(QueueName);
  
distQueue.Enqueue(new Customer {
	ContactName = "David Johnes", 
	CompanyName = "Lonesome Pine Restaurant"
});
String cacheName = "demoCache";
String queueName = "DistributedQueue:Customers";

// Initialize an instance of the cache to begin performing operations
Cache cache = CacheManager.getCache(cacheName);

// Create a thread-safe distributed queue visible to all cluster nodes
DistributedQueue<Customer> distQueue = cache.getDataStructuresManager().createQueue(queueName, Customer.class);

distQueue.add(new Customer("David Johnes", "Lonesome Pine Restaurant"));
distQueue.add(new Customer("Carlos Gonzalez", "LILA-Supermercado"));

As you can see above, a Distributed Queue allows you to add (Enqueue) items in a sequence so you can later remove (Dequeue) them in the same sequence (FIFO). Here is the Distributed Queue interface:

public interface IDistributedQueue<T> : IEnumerable<T>, IEnumerable, ICollection, IDistributedDataTypes, ILockable, INotifiable
  {
      void Clear();
      bool Contains(T item);
      void CopyTo(T[] array, int arrayIndex);
      T Dequeue();
      IList<T> DequeueBulk(int maxitems = 10);
      void Enqueue(T item);
      void EnqueueBulk(IList<T> items);
      T Peek();
      T[] ToArray();
  }
public interface DistributedQueue<T> extends Queue<T>, DistributedDataStructure, Notifiable {
    void clear();

    void copyTo(T[] var1, int var2);

    T peek();

    Object[] toArray();
}
 

Distributed HashSet

A Distributed HashSet behaves just like the .NET HashSet class, but in a shared manner for multiple applications and users. It provides all Set operations like:

  • - No duplicates: in the Set
  • - Set operations: like Union, Intersection, and Difference

Being a shared HashSet for multiple applications or users, this becomes a powerful data structure to use. Here is an example of how to use it.

string cacheName = "demoCache";
string hashSetName = "DistributedHashSet:UniqueValueHashSet";

// Initialize an instance of the cache to begin performing operations:
ICache cache = CacheManager.GetCache(cacheName);

// Creating a distributed HashSet with absolute expiration
IDistributedHashSet<string> hashSet;
hashSet = cache.DataTypeManager.CreateHashSet<string>(hashSetName);

// Create data for HashSet
var daysOfWeek = new string[] { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" };

// Add multiple entries to the HashSet
hashSet.AddRange(daysOfWeek);

// Since this entry already exists, no change to the HashSet is made by this call
hashSet.Add("Monday");
String cacheName = "demoCache";
String hashSetName = "DistributedHashSet:UniqueValueHashSet";

// Initialize an instance of the cache to begin performing operations:
Cache cache = CacheManager.getCache(cacheName);

// Creating a distributed HashSet with absolute expiration
DistributedHashSet<String> hashSet;
hashSet = cache.getDataStructuresManager().createHashSet(hashSetName, String.class);

// Add entries to the hashset
hashSet.add("Monday");
hashSet.add("Tuesday");
hashSet.add("Wednesday");
hashSet.add("Thursday");
hashSet.add("Friday");
hashSet.add("Saturday");
hashSet.add("Sunday");

// Since this entry already exists, no change to the hashset is made by this call
hashSet.add("Monday");

As you can see, when you add "Monday" the second time, it is not added to the HashSet.

 

Distributed Dictionary

A Distributed Dictionary (IDistributedDictionary) acts as a drop-in replacement for the regular .NET IDictionary interface, but in a shared manner for multiple applications and users. It provides all Dictionary operations like Add, Update, Remove, Contains, and more.

On top of regular Dictionary features, Distributed Dictionary provides the ability to expire items based on NCache expiration options like Absolute Expiration and Sliding Expiration.

ICache cache = CacheManager.GetCache("demoCache");
string dictName = "DistributedDictionary:Customers";

IDistributedDictionary<string, Customer> dict = cache.DataTypeManager.GetDictionary<string, Customer>(dictName);

if (dict == null)
{
	DataTypeAttributes attributes = new DataTypeAttributes {
		Expiration = new Expiration(ExpirationType.Absolute, new TimeSpan(0, 1, 0))
	};
	// Creating a distributed Dictionary with an absolute expiration of 1 minute
	dict = cache.DataTypeManager.CreateDictionary<string, Customer>(dictName, attributes);
}

Customer cust = new Customer
{	
	CustomerID = "customer1",
	ContactName = "David Johnes",
	CompanyName = "Lonesome Pine Restaurant",
	ContactNo = "(1) 408-354-9768",
	Address = "Silicon Valley, Santa Clara, California",
};
	   
dict.Add("customer1", cust);

Customer cachedCust;
bool fetched = dict.TryGetValue("customer1", out cachedCust);
String cacheName = "demoCache";
String dictName = "DistributedDictionary:Customers";
 
// Initialize an instance of the cache to begin performing operations
Cache cache = CacheManager.getCache(cacheName);

DistributedMap<String, Customer> dict = cache.getDataStructuresManager().createMap(dictName, Customer.class);

Customer customer = new Customer("David Johnes", "Lonesome Pine Restaurant", "Customer1", "(1) 408-354-9768");

dict.put("customer1", customer);
Customer cachedCustomer = dict.get("customer1");
 

Distributed List

Distributed List fully implements the System.Collections.Generic.IList<T> interface, allowing it to act as a drop-in replacement for standard Lists. The key difference is that it is distributed and can be shared across multiple applications and processes. Distributed List is an unsorted list, and you can add items either at the end of the list through the Add() method or at any location through the Insert() method by providing an index.

Below is an example of how to use a Distributed List.

ICache cache = CacheManager.GetCache("demoCache");
string listName = "DistributedList:Customers";

IDistributedList<Customer> distList = cache.DataTypeManager.GetList<Customer>(listName);

if (distList == null)
{
	DataTypeAttributes attributes = new DataTypeAttributes {
		Expiration = new Expiration(ExpirationType.Absolute, new TimeSpan(0, 1, 0))
	};

	// Creating Distributed List with absolute expiration of 1 minute
	distList = cache.DataTypeManager.CreateList<Customer>(listName, attributes);
}

Customer cust = new Customer
{
	CustomerID = "customer1",
	ContactName = "David Johnes",
	CompanyName = "Lonesome Pine Restaurant",
	ContactNo = "(1) 408-354-9768",
	Address = "Silicon Valley, Santa Clara, California",
};

distList.Add(cust);
Customer cachedCustomer = distList[0];
String cacheName = "demoCache";
String listName = "DistributedList:Customers";

// Initialize an instance of the cache to begin performing operations:
Cache cache = CacheManager.getCache(cacheName);

DistributedList distributedList = cache.getDataStructuresManager().createList(listName,   Customer.class);

Customer customer = new Customer("David Johnes", "Lonesome Pine Restaurant", "Customer1", "(1) 408-354-9768");

distributedList.add(customer);
Customer cachedCustomer = (Customer) distributedList.get(0);

You can also remove items from the list, iterate over it, and perform many other operations.

 

Distributed Counter

Distributed Counter is a powerful data structure in NCache that allows you to maintain a unique Counter in a distributed environment shared by multiple applications. This has a lot of uses and allows you to quickly develop applications around it. Below is an example:

ICache cache = CacheManager.GetCache("demoCache");
string counterName = "DistributedCounter:Customers";

ICounter counter = cache.DataTypeManager.GetCounter(counterName);
if (counter == null)
{
   DataTypeAttributes attributes = new DataTypeAttributes {
      Expiration = new Expiration(ExpirationType.Absolute, new TimeSpan(0, 1, 0))
   };

   // Creating Distributed Counter with absolute expiration to modify cache properties of the Counter, provide an instance of DataTypeAttributes in the second parameter
   counter = cache.DataTypeManager.CreateCounter(counterName, attributes);
}

counter.SetValue(1000);
long newValue = counter.IncrementBy(5);
newValue = counter.Value;
newValue = counter.DecrementBy(2);
String cacheName = "demoCache";
String counterName = "DistributedCounter:Customers";

// Initialize an instance of the cache to begin performing operations
Cache cache = CacheManager.getCache(cacheName);

Counter counter = cache.getDataStructuresManager().createCounter(counterName);
counter.setValue(1000);
long newValue = counter.incrementBy(5);
newValue = counter.getValue();
newValue = counter.decrementBy(2);

What to Do Next?

Frequently Asked Questions (FAQ)

Yes. NCache guarantees thread safety across the entire cluster. It uses internal distributed locking to manage concurrency, ensuring that simultaneous updates from multiple applications do not cause data corruption or race conditions.

A Distributed Dictionary is shared across processes and servers, whereas a standard Dictionary exists only in the local memory of a single application. Additionally, NCache supports data expiration (Absolute and Sliding) and high availability via replication, features not found in standard .NET collections.

The data remains available. Since the structures are hosted in the external NCache cluster (out-of-proc), they are independent of the application lifecycle. Your data survives application restarts, crashes, and deployments.

Minimal refactoring is required. NCache implements standard .NET interfaces like IDictionary<K,V> and IList<T>. You can use standard methods (like Add, Remove, Contains) and simply replace the object initialization to use the NCache handle.

© Copyright Alachisoft 2002 - . All rights reserved. NCache is a registered trademark of Diyatech Corp.