Ignite client node does not put data though server nodes to DB (with writeThrough only on server, without writeBehind) - gridgain

Could you please help me with following question:
I have the following configuration of partitioned cache cluster:
server nodes with writeThrough enabled. They are able to write data to DB by cacheStoreFactory=HibernateCacheStoreFactory
client nodes without writeThrough configuration but with clientMode=true
I perform put on client node, then I see, that this data is sent to server node, but server node performs put only to cache, but does not invoke cacheStoreFactory (writeThrough behaviour). So, data is only cached in cluster, but is not written to DB.
If I add writeThrough configuration to client nodes, writeThrough is invoked of course, but I would like to remove any dependencies on Hibernate from client nodes.
Also, if I enable writeBehind configuration on server side, then writeThrough functionality is invoked and server node, writes data from client node to DB asynchronously. But it does not satisfy my requirements, because I'd like to perform puts from client node in one transaction.
Is it possible to perform puts from client node to store data by server nodes with writeThrough in transaction without writeBehind?

Transactional cache writes to the persistence store from the node that initiated the transaction (in your case it's a client node). This is done because a transaction can potentially include entries that are stored on different nodes, and if the store will be also updated from different nodes, it would be impossible to maintain transactional consistency between cache and the database.
If you don't have access to the database on the client, you can send a closure to one of the servers and start a transaction there, like this:
Ignition.ignite().compute().run(new IgniteRunnable() {
#IgniteInstanceResource
private Ignite ignite;
#Override public void run() {
try (Transaction tx = ignite.transactions().txStart()) {
// Cache operations go here...
tx.commit();
}
}
});

Related

Need more insight into Hazelcast Client and the ideal scenario to use it

There is already a question on the difference between Hazelcast Instance and Hazelcast client.
And it is mentioned that
HazelcastInstance = HazelcastClient + AnotherFeatures
So is it right to say client just reads and writes to the cluster formed without getting involved in the cluster? i.e. client does not store the data?
This is important to know since we can configure JVM memory as per the usage. The instances forming the cluster will be allocated more than the ones that are just connecting as a client.
It is a little bit more complicated than that. The Hazelcast Lite Member is a full-blown cluster member, without getting partitions assigned. That said, it doesn't store any data but otherwise behaves like a normal member.
Clients on the other side are simple proxies that have to forward everything to one cluster member to get any operation done. You can imagine a Hazelcast client to be something like a JDBC client, that has just enough code to connect to the cluster and redirect requests / retrieve responses.

Connect to ElastiCache cluster via Node.js

I'm confused as to how to connect to AWS's ElastiCache Redis via Node.js. I've successfully managed to connect to the primary host (001) via the node_redis NPM, but I'm unable to use the clustering ability of ioredis because apparently ElastiCache doesn't implement the CLUSTER commands.
I figured that there must be another way, but the AWS SDK for Node only has commands for managing ElastiCache, not for actually connecting to it.
Without using CLUSTER, I'm concerned that my app won't be able to fail over if the master node fails, since I can't fall back to the other clusters. I also get errors from my Redis client, Error: READONLY You can't write against a read only slave. when the master switches, which I'm not sure how to handle gracefully.
Am I overthinking this? I am finding very little information about using ElastiCache Redis clusters with Node.js.
I was overthinking this.
Q: What options does Amazon ElastiCache for Redis provide for node failures?
Amazon ElastiCache for Redis will repair the node by acquiring new service resources, and will then redirect the node's existing DNS name to point to the new service resources. Thus, the DNS name for a Redis node remains constant, but the IP address of a Redis node can change over time. If you have a replication group with one or more read replicas and Multi-AZ is enabled, then in case of primary node failure ElastiCache will automatically detect the failure, select a replica and promote it to become the new primary. It will also propagate the DNS so that you can continue to use the primary endpoint and after the promotion it will point to the newly promoted primary. For more details see the Multi-AZ section of this FAQ. When Redis replication option is selected with Multi-AZ disabled, in case of primary node failure you will be given the option to initiate a failover to a read replica node. The failover target can be in the same zone or another zone. To failback to the original zone, promote the read replica in the original zone to be the primary. You may choose to architect your application to force the Redis client library to reconnect to the repaired Redis server node. This can help as some Redis libraries will stop using a server indefinitely when they encounter communication errors or timeouts.
The solution is to connect to the primary master node only, without using any clustering on the client side. When the master fails, the slave is promoted and the DNS is updated so that the slave will become the primary node, without the host needing to change on the client's side.
To prevent temporary connectivity errors when the failover happens, you can add some configuration to ioredis:
var client = new Redis(port, host, {
retryStrategy: function (times) {
log.warn('Lost Redis connection, reattempting');
return Math.min(times * 2, 2000);
},
reconnectOnError: function (err) {
if (err.message.slice(0, targetError.length) === 'READONLY') {
// When a slave is promoted, we might get temporary errors saying
// READONLY You can't write against a read only slave. Attempt to
// reconnect if this happens.
log.warn('ElastiCache returned a READONLY error, reconnecting');
return 2; // `1` means reconnect, `2` means reconnect and resend
// the failed command
}
}
});

how to make astyanax prefer local DC?

I know that Astyanax has options to make it only use the local DC, but according to this link, the client will then fail if the nodes in the local DC go down. I was wondering if there was something similar to this (a configuration setting), where requests would go to nodes in the local DC if the data exists on one of the nodes, and only access cross data center nodes when absolutely necessary.
Not a configuration setting, but you could achieve it using the following workaround. Have two drivers initialized driver_dc1 and driver_dc2 in your setup where each one connects to the nodes of the pertinent data center.
try{
// perform operation using driver_dc1
}catch(ConnectionException e){
// perform operation using driver_dc2
}

How do Cassandra Clients Learn About New Nodes?

If a Cassandra client is given a list of nodes at startup, how does it learn that other nodes exist?
For instance, a client knows a single node IP and asks it for some data. That node acts as a coordinator, finding other nodes in the cluster that hold the data the client requested. The coordinator returns. Is there any part of the Cassandra binary protocol that returns the external address of the node delegated to, along with the requested data?

How to configure Astyanax connection pool to dismiss any client requests (single Cassandra node development environments)

in a Cassandra/Astyanax development environment, I'm running a single/local Cassandra node. When this single Cassandra node goes down (for whatever reason), any Astyanax based client code (mutation batch, queries ...) fail with something like that:
com.netflix.astyanax.connectionpool.exceptions.NoAvailableHostsException: NoAvailableHostsException: [host=None(0.0.0.0):0, latency=0(0), attempts=0]No hosts to borrow from
at com.netflix.astyanax.connectionpool.impl.RoundRobinExecuteWithFailover.<init>(RoundRobinExecuteWithFailover.java:30)
at com.netflix.astyanax.connectionpool.impl.TokenAwareConnectionPoolImpl.newExecuteWithFailover(TokenAwareConnectionPoolImpl.java:80)
at com.netflix.astyanax.connectionpool.impl.AbstractHostPartitionConnectionPool.executeWithFailover(AbstractHostPartitionConnectionPool.java:248)
at com.netflix.astyanax.thrift.ThriftColumnFamilyQueryImpl$4.execute(ThriftColumnFamilyQueryImpl.java:532)
and this exception is logged for each subsequent Astyanax-based client request, resulting in the above log spam. Basically, I'm asking if there is a way to configure an Astyanax connection pool in a way to stop accepting requests and ideally provide some sort of callback which allows me to shutdown my Astyanax-based client application (e.g. our server application).
What you want to do is a bad choice, the whole point of Cassandra is to build a distributed, multi-node cluster which can handle failures, however you could catch that specific exception and disregard it in java without doing the costly logging.
try {
// lots of C* stuff
} catch (NoAvailableHostsException ex) {
// Swallow exception
}
Also Astyanax doesn't accept requests, its an API not a server, Cassandra is the server. You can tell Cassandra to stop excepting requests using the JMX functionality. You could invoke a call to the stopRPCServer() JMX function in org.apache.cassandra.db.StorageService.

Resources