Wednesday, 11 January 2017

Near Cache for native C++/C# Client example

Dear Readers,

as mentioned in our previous post about the new C++/C# release 8.1.0.Beta1, clients are now equipped with near cache support.

The near cache is an additional cache level that keeps the most recently used cache entries in an "in memory" data structure. Near cached objects are synchronized with the remote server value in the background and can be get as fast as a map[] operation.

So, your client tends to periodically focus the operations on a subset of your entries? This feature could be of help: it's easy to use, just enable it and you'll have near cache seamless under the wood.

A C++ example of a cache with near cache configuration
int main(int argc, char** argv) {
ConfigurationBuilder confBuilder;
confBuilder.addServer().host("127.0.0.1").port(11222);
confBuilder.protocolVersion(Configuration::PROTOCOL_VERSION_24);
confBuilder.balancingStrategyProducer(nullptr);
// Enable the near cache support
confBuilder.nearCache().mode(NearCacheMode::INVALIDATED).maxEntries(4);
The last line does the magic, the INVALIDATED mode is the active mode for the near cache (default mode is DISABLED which means no near cache, see Java docs), maxEntries is the maximum number of entries that can be stored nearly. If the near cache is full the oldest entry will be evicted. Set maxEntries=0 for unbounded cache (do you have enough memory?)
Now a full example of application that just does some gets and puts and counts how many of them are served remote and how many are served nearly. As you can see the cache object is an instance of the "well known" RemoteCache class
#include "infinispan/hotrod/ConfigurationBuilder.h"
#include "infinispan/hotrod/RemoteCacheManager.h"
#include "infinispan/hotrod/RemoteCache.h"
#include "infinispan/hotrod/Version.h"
#include "infinispan/hotrod/JBasicMarshaller.h"
#include <string>
int main(int argc, char** argv) {
ConfigurationBuilder confBuilder;
confBuilder.addServer().host("127.0.0.1").port(11222);
confBuilder.protocolVersion(Configuration::PROTOCOL_VERSION_24);
confBuilder.balancingStrategyProducer(nullptr);
// Enable the near cache support
confBuilder.nearCache().mode(NearCacheMode::INVALIDATED).maxEntries(4);
RemoteCacheManager cacheManager(confBuilder.build(), false);
JBasicMarshaller<std::string> *km = new JBasicMarshaller<std::string>();
JBasicMarshaller<std::string> *vm = new JBasicMarshaller<std::string>();
cacheManager.start();
RemoteCache<std::string, std::string> cache = cacheManager.getCache<std::string, std::string>(km,
&Marshaller<std::string>::destroy,
vm,
&Marshaller<std::string>::destroy);
// Clear cache to have clean counters
cache.clear();
// Read stats to do some checks on hits and misses counters
std::map<std::string,std::string> statsBegin= cache.stats();
auto hitsBegin = std::stoi(statsBegin["hits"]);
auto missesBegin = std::stoi(statsBegin["misses"]);
// Only the first get goes to the remote cache and miss the value
// then all the gets are resolved nearly
cache.get("key1"); // remote misses++
cache.put("key1", "value1");
std::string *rest = cache.get("key1"); // near
std::cout << "Got result from near cache:" << ((rest) ? *rest : "null") << std::endl;
delete rest;
rest = cache.get("key1"); // near
delete rest;
// fill the near cache with 4 more entries (5 total)
cache.put("key2", "value2");
cache.put("key3", "value3");
cache.put("key4", "value4");
cache.put("key5", "value5");
// now key1 one should not be near
cache.get("key1"); // remote hits++. Stored near (this delete key2 nearly)
cache.get("key2"); // remote hits++. Stored near (this delete key3 nearly)
cache.get("key1"); // near
std::map<std::string,std::string> statsEnd= cache.stats();
auto hitsEnd = std::stoi(statsEnd["hits"]);
auto missesEnd = std::stoi(statsEnd["misses"]);
std::cout << "Remote hits should be 2 remote misses should be 1: " << std::endl;
std::cout << "Remote hits is: " << hitsEnd-hitsBegin << "" << std::endl;
std::cout << "Remote misses is: " << missesEnd-missesBegin << "" << std::endl;
}
Entries values in the near cache are kept aligned with the remote cache state via the events subsystem: if something changes in the server, an update event (modified, expired, removed) is sent to the client that updates the cache accordingly.

By the way: do you know that C++/C# clients can subscribe listener to events? In the next "native" post we will see how.

Cheers!
and thank you for reading.

No comments:

Post a Comment