 | This documentation applies to the Push Replication Pattern 2.2.0. The latest Push Replication Pattern documentation is available here. |
The Push Replication Pattern
This is an example implementation of Push Replication pattern.
The Push Replication Pattern advocates that;
- Operations (such as insert, update and delete) occurring on Data in one Location should be pushed using one or more Publishers to an associated Device.
- A Publisher is responsible for optimistically replicating Operations (in the order in which the said Operations originally occurred) on or with the associated Device.
- If a Device is unavailable for some reason, the Operations to be replicated using the associated Publisher will be queued and executed (in the original order) at a later point in time.
This implementation of the Push Replication Pattern additionally advocates that;
- The Data on which Operations occur are standard Coherence Cache Entries.
- The Operations are called EntryOperations.
- A Location is a Coherence Cluster.
- A Location may act as both a sender of Operations and receiver of Operations. That is, multi-way multi-location push replication is permitted.
- A Device may be anyone of the following; a local cluster, a remote cluster, a file system, a database, an i/o stream, a logging system etc.
|
Outline
Rationale
The purpose of this pattern is to provide extensible, flexible, high-performance, highly-available and scalable infrastructure to support the replication of EntryOperations occurring in one Coherence Cluster to one or more possibly globally distributed other Coherence Clusters.
While this naturally forms a "hub-and-spoke" architecture of federated Coherence Clusters, by configuring each Coherence Cluster as a "hub" and a "spoke", multi-way push replication may be achieved. |
What's New?
The following changes have been made since the Push Replication Pattern 2.1.1 release to produce this release.
- Added the name of the originating site (siteName) and cluster (clusterName) to the EntryOperation class to permit extensive conflict resolution and perhaps later, site and/or cluster-based filtering.
- Renamed the com.oracle.coherence.pushreplication.publishers.CachePublisher to com.oracle.coherence.pushreplication.publishers.LocalCachePublisher to correctly represent the scope of operations being performed.
- Created the new interface CachePublisher to standardize the methods for publishing to caches (either locally or remotely)
- Created the new interface CachePublisher.ConflictResolver that may be used to specifically control how EntryOperations are executed when they are published by a CachePublisher. This allows developers complete control over how EntryOpersions are performed, including the ability to override and resolve potential conflicts with existing cache entries.
- Refactored RemoteCachePublisher to inherit it's base implementation from the LocalCachePublisher (and thus support conflict resolution with a CachePublisher.ConflictResolver ).
- Modified the coherence-pushreplicationpattern-*cache-config.xml so that the "pending-operations-cache" is enabled by default (if it's not used it will have no cost anyway).
- Renamed SafeCachePublisher to SafeLocalCachePublisher to correctly reflect scope of use.
- Enhanced the SafeLocalCachePublisher to allow specification of a CachePublisher.ConflictResolver
- Added the protected publishEntryOperation method to the PublishingCacheStore to optimize the SafePublishingCacheStore implementation
- Fixed potential race-condition when multiple sites attempt to execute an EntryOperation on a remote site on the same Cache Entry at exactly the same time.
- Added the ability for Publishers and BatchPublishers to specify the number of consecutive failures before their associated PublishingService is suspended
- Added the ability to specify if BatchPublishers should automatically start publishing when they are registered (or they start in suspended mode).
- Added the ability to suspend and resume PublishingServices through JMX. This allows us to start suspended Publishing services, or suspend them when necessary.
- Introduced the PushReplicationManager class (and DefaultPushReplicationManager implementation) to simplify the registration of BatchPublishers - no longer need to use the messaging layer.
- Added a "deploy" target to the build.xml to simplify deployment to a repository (when not using Maven)
Implementation Discussion
 | Before you start
The Push Replication Pattern makes extensive use of the Store and Forward Messaging Pattern as infrastructure to capture EntryOperations and deliver them in-order of occurrence to BatchPublishers. Consequently may be beneficial for you to get familiar with the Store and Forward Messaging Pattern (and it's implementation) to understand the implementation of this pattern. |
The Push Replication Pattern is an extension of the Store and Forward Messaging Pattern. The implementation provides several new Coherence CacheStore implementations, namely the PublishingCacheStore (for "hub-and-spoke" push replication) and the SafePublishingCacheStore (for "multi-way" push replication), that are used to capture cache mutation operations (like insert, update and delete) on cache entries.
After such operations are captured (represented as EntryOperations) they are sent to the messaging layer (implemented using the Store and Forward Messaging Pattern) for distribution to specialized TopicSubscriptions called PublishingSubscriptions.
When PublishingSubscriptions receive the EntryOperations from the messaging layer, an internal event (captured by a backing-map-listener executing in the same JVM in which the PublishingSubscription is being managed by Coherence) signals to a PublishingService to commence publishing the currently queued EntryOperations with an associated BatchPublisher implementation. How the ultimate publishing occurs is entirely dependent on the implementation of the BatchPublisher.
The following diagram provides an overview of the push replication process through the various layers of the system.

The following section provides an example use of the push replication pattern, including establishing publishers.
Example
Step 1: Configuring a Cache (with a PublishingCacheStore)
As push replication occurs on a cache-by-cache basis, the first step in making use of this pattern is configuring your application cache(s) to use an appropriate PublishingCacheStore implementation. For the "hub-and-spoke" model, where one cluster is a "master" and the other clusters are "spokes", you should use a PublishingCacheStore. For multi-way push replication, your cache(s) should be configured to use a SafePublishingCacheStore.
By default, the Push Replication cache configuration (coherence-pushreplicationpattern-pof-cache-config.xml) defines a "publishing-*" mapping to a distributed-scheme that is configured to use a PublishingCacheStore. Consequently any cache name prefixed with "publishing-" will automatically support Push Replication.
String cacheName = "publishing-cache";
NamedCache namedCache = CacheFactory.getCache(cacheName);
When your application first accesses a "publishing-*" based scheme (which in turn creates the PublishingCacheStore), the underlying messaging infrastructure will be created to support Push Replication. This includes establishing a Topic that is named exactly the same as your cache. In this case, a Topic called "publishing-cache" will be created in the messaging layer.
From here on any operation that mutates the "publishing-cache" will have the said operation captured and sent (as an EntryOperation) to the "publishing-cache" Topic, after which the operation will be forwarded in-order to the Subscriptions on the said Topic.
Step 2: Registering a BatchPublisher to perform Push Replication
Until a BatchPublisher is registered for a cache configured with a PublishingCacheStore, no publishing will occur. To register a BatchPublisher to publish EntryOperations, you need to use a PushReplicationManager.
PushReplicationManager pushReplicationManager = DefaultPushReplicationMananger.getInstance();
pushReplicationManager.registerBatchPublisher("publishing-cache", "stderr-publisher", new BatchPublisherAdapter(new StdErrPublisher()));
There are essentially two forms of publishers; those that support "batching" and those that don't. By default, the Push Replication pattern only works with BatchPublishers. Consequently to use a non-batching publisher (ie: an implementation of the Publisher interface), an adapter has been provided. The package com.oracle.coherence.pushreplication.publishers provides numerous implementations of Publishers and BatchPublishers together with adapters to convert between them (as demonstrated in the example above)
Step 3: Using a publishing- cache.*
Once you've registered one or more BatchPublishers for each cache from which you would like to publish EntryOperations, you may simply use the said cache(s) as regular caches (as they are!).
Hence the following code, registered with the above "stderr-publisher", would output the "put" operations to stderr.
namedCache.put("australian-welcome", "Gudday");
namedCache.put("regular-welcome", "Hello");
namedCache.put("french-welcome", "Bonjour");
Frequently Asked Questions
How can the Push Replication Publishers be monitored?
Like the Command Pattern this pattern is JMX ready. By simply enabling JMX on the Coherence Cluster, each of the PublishingServices will be presented in the JMX tree, detailing current replication state and statistics.
How do I enable Push Replication to one or more (remote) Coherence Clusters?
In order to publish to a remote cluster, you must;
- Configure and enable one or more proxies on the remote cluster(s).
- Ensure that the members of the remote cluster(s) have the Push Replication Pattern (and dependencies) in the class path
- Configure and enable one or more Remote Invocation Services in the "hub" with the addresses of the remote cluster proxy members (of it you're using Coherence 3.4+, use an AddressProvider). An example scheme is defined in the coherence-pushreplicationpattern-cache-config.xml file.
- Register appropriate RemoteInvocationPublishers for each cache (as follows).
String remoteCacheName = cacheName; pushReplicationManager.registerBatchPublisher(cacheName,
"remote-site",
new RemoteInvocationPublisher("RemoteSiteInvocationService", new BatchPublisherAdapter(new LocalCachePublisher(remoteCacheName)),
false, 10000, 100, 10000, 5));
How are conflicts resolved when replicating EntryOperations in remote clusters?
The LocalCachePublisher, SafeLocalCachePublisher and RemoteCachePublisher classes support the specification of a CachePublisher.ConflictResolver implementation during construction. By implementing a CachePublisher.ConflictResolver your application may resolve any underlying Entry conflicts in an appropriate manner. If not specified, the LocalCachePublisher.BruteForceConflictResolver is used.
References and Additional Information