The use of NCache spans a variety of use cases, starting from a simple key-value store to advanced SQL searching and Pub/Sub. Client applications include, but are not limited to, console application, windows services, web applications, and web services. Client libraries (SDK) include .NET, Java, and NodeJS. Moreover, support for Python and Scala is also provided. Using the relevant SDK, client applications can connect with one or more caches.
Google Protobuff as data exchange format: The client communicates with cache over a persistent TCP socket. NCache client uses Google Protocol buffer (protofbuf) as a protocol to communicate with the cache server. The use of Protobuff provides flexibility to older client versions of NCache to communicate with new cache server versions.
Request-Response based parallel request execution: NCache client supports multi-threading. Applications can make parallel requests to the cache. NCache follows RequestId based request-response protocol in client-server communications where every request is assigned a unique RequestId. Despite having a single TCP connection between the cache client and a cache server, the client can send multiple requests with their unique RequestIds to the cache server without waiting for the response of already sent requests. So each request is truly independent. NCache server also supports parallel request execution. This architecture enables applications to execute multiple parallel operations from the client to cache servers without operations waiting for each other, thus providing maximum performance and scalability.
Request Pipelining: Pipelining refers to combining and sending multiple requests in a single socket (I/O) operation. Whenever applications perform I/O operations, user to kernel mode switching occurs, which is a costly operation. Pipelining avoids this cost by performing the same task in less number of I/O operations. Pipelining increases application performance manifold. NCache supports pipelining on both client and server end.
Cache topology awareness: NCache client is cache topology-aware. When a cache client connects to the first cache server, it retrieves the cache metadata, including its topology. How a cache should establish connectivity with cache servers and how client operations should be executed, depends on the underlying topology of the cache. For example, data is distributed among different cache servers in Partitioned and Partition-Replica topologies. Therefore the client establishes a TCP connection with each server in the cache cluster and fetches the latest data distribution maps. Then client directly performs read and write operations against the partition containing the concerned data. Similarly, each server in the Replicated topology contains the same set of data. Thus client only connects with a single cache server.
Handling connection failures in a seamless fashion: NCache client maintains a persistent connection with the cache server(s). If this connection breaks due to network glitches, the NCache client is equipped with a background connection re-establishment mechanism. This mechanism automatically establishes connectivity with the failed server as soon as network connectivity is resumed between the client and server. And, all of this happens seamlessly without client application intervention.
Data Serialization: Application data goes through the serialization process before going to the cache server. NCache supports both Binary and JSON serialization. You can choose either of the serializations formats at the time of configuring the cache. The cache client fetches the serialization format from the cache server upon connecting to the cache. Then it serializes the application data according to the serialization format.
Data Encryption: Encrypting of application data is an optional feature that you can enable. If encryption is configured, the client encrypts application data after it has been serialized. The client fetches the encryption-related configuration from the cache server upon connecting to the cache.
Data Compression: Compression of the application data can help reduce cache size if the data is really large. Data is first serialized, then encrypted (if encryption is enabled), and finally compressed by the cache client before being dispatched to the cache. The cache client fetches the compression-related configuration from the cache server upon connecting to the cache.
Connecting With the Cache
Cache client needs the server information to connect with the cache. Server information can be either provided through the client configuration file (client.ncconf ) or through CacheConnectionOptions . The client iterates through the provided cache server list and tries to connect with the cache running on the server. If the cache instance is not running on a given server, it moves to the next server provided in the list. Client connection usually goes through the following steps:
The client first establishes a TCP connection with NCache service over port 9800.
The client then makes a request for the complete list of configured cache servers. This way, it has an updated list of the cache servers.
The client then sends the cache an initialization request to the server, which includes the cache name and security credentials in case cache security is enabled. Every cache runs in a separate process. If you have .NET Framework based installation of NCache on the server end, then the service seamlessly hands over client connection to the cache process, and the client successfully connects with the cache. In .NET Core or .NET 6 and higher installations, the service shares the port information with the client on which the cache is listening for connections. The client then establishes a direct connection with the cache process and sends an initialization request.
NCache automatically configures the Firewall to open all the required ports on Windows. However, you need to open NCache ports on Linux by Configuring Firewall.
If the client is connecting with a Replicated cache and client load balancing is enabled, then the client asks for a server that has the least number of clients connected to it. It then connects with the least loaded server.
If the client is connecting with a Partitioned or a Partition-Replica cache, then it requests the distribution maps for the servers. Upon receiving the map(s), it establishes connections with the cache servers present in the distribution map.
Client also requests for different cache configurations like