Showing posts with label asynchronous. Show all posts
Showing posts with label asynchronous. Show all posts

Friday, 18 February 2011

5.0.0.ALPHA3 is here with more goodies!

For those who can't wait to get hold on the newest Infinispan features, we've just released the third alpha release of the 5.0 series, called 5.0.0.ALPHA3.

Apart from including fixes in 4.2.1.CR2, it allows users to prefetch data in advance in parallel thanks to the new getAsync() method. Why is this useful? Imagine the following scenario: A cache is configured with distribution and an app that requires values associated with k1, k2, and k3 in order to do its job. In the worst case scenario assume that all these keys located in remote nodes. Previously, before 5.0.0.ALPHA3, you'd have written something like this:


Value v1 = cache.get("k1");
Value v2 = cache.get("k2");
Value v3 = cache.get("k3");

The problem with this code is that each get() is sequential, so the second get() call must wait for first get() to retrieve data from the remote node before it can execute. This is clearly not very optimal. From 5.0.0.ALPHA3 onwards, you can do this instead:


NotifyingFuture<Value> f1 = cache.getAsync("k1");
NotifyingFuture<Value> f2 = cache.getAsync("k2");
NotifyingFuture<Value> f3 = cache.getAsync("k3");
...
Value v1 = f1.get(); // blocks until value has been returned
Value v2 = f2.get();
Value v3 = f3.get();

The clear advantage here is that the get requests, via getAsync(), can be fired in parallel and they don't need to wait for each other. Afterwards, when the value is needed, simply call get() on the future received.

Amongst other API enhancements, such as RemoteCache implementing size() and isEmpty(), or the ability to delete AtomicMap instances via AtomicMapLookup, it's worth highlighting that we've taken your feedback on board with regards to how Infinispan is configured programmatically, and from 5.0.0.ALPHA3 onwards, we provide a more fluent way of configuring Infinispan. For example:


GlobalConfiguration gc = new GlobalConfiguration();

GlobalJmxStatisticsConfig jmxStatistics = gc.configureGlobalJmxStatistics();
jmxStatistics.allowDuplicateDomains(true).enabled(true);

TransportConfig transport = gc.configureTransport();
transport.clusterName("blah").machineId("id").rackId("rack").strictPeerToPeer(true);

You can find more examples of this new configuration here. Note that this fluent API is likely to evolve further before we go final with 5.0.0 as shown in this forum discussion, but please keep your feedback coming! Finally, details of what's fixed is in the release notes. As always, please use the user forums to report back, grab the release here, enjoy and keep the feedback coming.

Cheers,
Galder

Thursday, 14 May 2009

Alpha3 ready to rumble!

So I've just tagged and cut Infinispan 4.0.0.ALPHA3. (Why are we starting with release 4.0.0? Read our FAQs!)

As I mentioned recently, I've implemented an uber-cool new asynchronous API for the cache and am dying to show it off/get some feedback on it. Yes, Alpha3 contains the async APIs. Why is this so important? Because it allows you to get the best of both worlds when it comes to synchronous and asynchronous network communications, and harnesses the parallelism and scalability you'd naturally expect from a halfway-decent data grid. And, as far as I know, we're the first distributed cache - open or closed source - to offer such an API.

The release also contains other fixes, performance and stability improvements, and better javadocs throughout. One step closer to a full release.

Enjoy the release - available on our download page - and please do post feedback on the Infinispan User Forums.

Cheers
Manik

Wednesday, 13 May 2009

What's so cool about an asynchronous API?

Inspired by some thoughts from a recent conversation with JBoss Messaging's Tim Fox, I've decided to go ahead and implement a new, asynchronous API for Infinispan.

To sum things up, this new API - additional methods on Cache - allow for asynchronous versions of put(), putIfAbsent(), putAll(), remove(), replace(), clear() and their various overloaded forms. Unimaginatively called putAsync(), putIfAbsentAsync(), etc., these new methods return a Future rather than the expected return type. E.g.,


V put(K key, V value);
Future<V> putAsync(K key, V value);

boolean remove(K key, V value);
Future<Boolean> removeAsync(K key, V value);

void clear();
Future<Void> clearAsync();

// ... etc ...

You guessed it, these methods do not block. They return immediately, and how cool is that! If you care about return values - or indeed simply want to wait until the operation completes - you do a Future.get(), which will block until the call completes. Why is this useful? Mainly because, in the case of clustered caches, it allows you to get the best of both worlds when it comes to synchronous and asynchronous mode transports.

Synchronous transports are normally recommended because of the guarantees they offer - the caller always knows that a call has properly propagated across the network, and is aware of any potential exceptions. However, asynchronous transports give you greater parallelism. You can start on the next operation even before the first one has made it across the network. But this is at a cost: losing out on the knowledge that a call has safely completed.

With this powerful new API though, you can have your cake and eat it too. Consider:



Cache<String, String> cache = getCache();
Future<String> f1 = cache.putAsync(k1, v1);
Future<String> f2 = cache.putAsync(k2, v2);
Future<String> f3 = cache.putAsync(k3, v3);

f1.get();
f2.get();
f3.get();


The network calls - possibly the most expensive part of a clustered write - involved for the 3 put calls can now happen in parallel. This is even more useful if the cache is distributed, and k1, k2 and k3 map to different nodes in the cluster - the processing required to handle the put operation on the remote nodes can happen simultaneously, on different nodes. And all the same, when calling Future.get(), we block until the calls have completed successfully. And we are aware of any exceptions thrown. With this approach, elapsed time taken to process all 3 puts should - theoretically, anyway - only be as slow as the single, slowest put().

This new API is now in Infinispan's trunk and yours to enjoy. It will be a main feature of my next release, which should be out in a few days. Please do give it a spin - I'd love to hear your thoughts and experiences.