GRIDtoday AMD

DAILY NEWS AND INFORMATION FOR THE GLOBAL GRID COMMUNITY /
  ( Table of Contents )  
Special Features:

HOW TO DEAL W/ DISTRIBUTED COLLECTIONS AND SETS USING JavaSpaces
By Avi Kapuya

Distributed Environments

Many distributed applications require data structures such as collections, sets, sorted sets, etc. in order to enable very fast work mode for different modules in the applications.

One of the examples I'm focusing in this article is from the financial world and is called "The Order Book". The Order Book is merely a list of orders posted to a marketplace by different sellers and buyers of merchandise in this marketplace. The Order is used very often. In fact, it is used every time someone looks at prices in the market or wishes to buy or sell stocks or options or even FX and browsing or updating the Order Book occurs thousands, or even hundreds of thousands times per second on the trading system, and many times, access to the Order Book is done in order to perform scans and searches using parameters such as price and time of arrival. For architects, the only way to provide reasonable access time to that part of the system is to have the Order Book in memory, as long as it is possible.

Today's prices of memory for servers, though, enable to have large amount of memory available for the applications, providing much better performance overall; especially, when memory is utilized properly by that application. Event based programming allows system designers to create very efficient design for In memory Order Books or any other collections, which are updated and queried at very high rates, however, in many cases, even such high performance provided by in-memory data collections is not enough and creating highly available, properly load balanced systems is getting to be very complicated and expensive. New level of performance and simplicity can only be achieved by introducing new approach and as a result, new paradigm and tools to move to the next level. The situation described here is similar to the development of aviation in the last era, starting from propeller engine that could drive an airplane to a certain speed and could carry limited weight.

Those old flying machines were sufficient for the time, but when more passengers and merchandise had to be flown at higher speeds, those engines failed and held the aviation industry back, until a new engine emerged, the Jet Engine. The Jet Engine was practically a miracle; It is very simple, consumes less fuel, can reach much higher speeds and carry much more weight. It is a significant improvement in every aspect of operation.

Computers today are already withholding the Jet engines within them in the form of multitude of ultra fast CPU's, loads of memory, fast storage and networking. However, Jet engines cannot fly themselves, and one engine cannot fly a Jumbo jet. It is necessary to add up few engines, plus a suitable body and wings, than it takes a well designed control and management system, which includes failover, high availability and load balancing, only than we can have that marvelous creation called Jumbo Jet, which can carry hundreds of people fast and safe to their destinations.

High performance information systems designers are facing a major dilemma these days, "should we get a bigger box?" or should we break the "We need a bigger box" paradigm and restructure our systems into distributed ones. The funny thing is, bigger boxes don't do the job anymore. The only conclusion is that systems must be redesigned in order to be able to work not only on multiple boxes but in many cases, on top of a geographically distributed network. Distributed Systems essentials

The first tools required by system designers are Data Collections and Sets, and in this article I will discuss a paradigm that handles those Data structures and others in distributed environments and gain memory level performance but in much larger scale. Let's start with an illustration:

Seen here, is a set of three servers, running the same applications. Within each application instance, there is an embedded JavaSpaces instance and a Sorted Set. The three JavaSpaces instances are configured to replicate objects from their space to all the other spaces in that cluster (simple replication configuration). Zooming into one of the servers, here is what we see:

Entries are written locally to the Sorted Set and are inserted into the set immediately. In addition, the Set update methods are also updating the JavaSpaces objects, essentially, writing or updating (using take and write) the object into the space. To avoid feedback of update into the set again, it is necessary to filter entries that are written locally by the Event Listener. The result of this sequence of operations is that locally, the set is updated immediately, the state of the space is than updated and the operations and new entries are replicated to other spaces located on other servers. As a result, on the other servers, the notification triggers update of the local set with the new object. In a very short time, the system is fully synchronized, yet we have not touched the issue of locking and ownership, I'll dedicate a section for these two important subjects.

Locking And Ownership Or "Single System Image" On Top Of Peer To Peer Clusters Of Memory

Single System image is a requirement many system designers put in place to avoid data inconsistency, however, it must be stated strongly that SSI and performance is a contradiction in terms due to long update cycles and information retrieval in SSI solutions, therefore, the paradigms we are demonstrating here provides most of the SSI requirements and for a very small price. It is clear that true SSI system cannot serve the operation of a large or even medium scale exchanges or banks. With the right design in place, one that takes in consideration the possibility of information being "stale" for a short time (between few milliseconds to 0.1 second), those systems can perform much faster than any other architecture. If you think about it, the same problems exist in databases, users are retrieving information from the databases and update it, by the time the transaction is committed other users see old data; The phenomena is called "Dirty Read." The solution provided here to attack this issue is ownership.

Ownership ties objects to specific servers in terms of modifications. Ownership can prevent from different entities to update an object at the same time. The method to implement ownership using JavaSpaces is by having the Write and Take operations use Hash-based distribution so operations on specific Entry with specific ID is always routed to the same space. Some JavaSpaces providers offers operation level load balancing, which is based on the Entry's hash code and can be set by the system designer. The performance is gained by allowing read operations from collections in a very fast manner (memory level Hashtable or Treeset), reaching up to hundreds of thousands of operations per second. When an entry is updated, the operations are directed to a specific space, which is the "owner" of that entry. Once updated, the updated information is distributed across the cluster and the collections are fully synchronized in a very short time. There are also extensions to the basic API offered by JavaSpaces such as atomic update with lock or batch JavaSpaces operations (writing / reading multiple entries in one call), which can be used to optimize the work with distributed shared memory and gain even better performance. The benefits of the Distributed Collections architecture is in the ability to work with in-memory collections and sets, defined by the system designer and have those objects distributed across multiple servers. The performance gain in using these paradigms is 2-3 orders of magnitude faster than using databases or other "propeller" solutions.

How Is High Availability, Load Balancing And Failover Achieved?

High availability, load balancing and failover are solved by using the Jini framework, which is using smart proxies on the client side. Those smart proxies are instantiated objects loaded from the server that the client connects to. Those objects are in fact connectors to a service, in the case of JavaSpaces, they are connectors to the space, which can and in few implementations indeed contain load balancing, high availability and failover policies, according to the configuration on the JavaSpaces cluster.

Jini lookup services allow clients to look for and discover space instances as they start and register in Jini lookup services, so in fact, when a client tries to connect to a Jini service, they don't have to know the exact network address they need to connect to, only the service they are looking for. In the case of JavaSpaces, each space, which is a member of the cluster, provides the client with the cluster different policies for failover, high availability and load balancing. On the configuration side, advanced implementations of clustered JavaSpaces such as GigaSpaces, enables to create different cluster configurations, which include replication, full or partial, of entries as well as replication of operations. It provides different out-of-the-box load balancing and failover policies such as round robin, hash based and more. Some implementations even offer replication matrixes with different replication policies between different servers which are asymmetric, such as one way replication or replication of specific type of information and other lower resolution relationships between spaces. JavaSpaces can also be configured to persist information into databases, rather than have everything in memory. This type of configuration is particularly useful for large amounts of data, which is difficult to keep even on multiple machines and can serve for recovery of data in case of system shutdown.

( Top of Page )
  ( Table of Contents )