Cache Replicator



Replicates cache operations across multiple caches


It can be common for multiple server-side DLLs to each have a local cache of the same data. For example, in a scaled up application, server A and server B each runs an instance of the ProductManager component. This component implements and maintains a local cache of all available products. Because client requests are stateless and can go to either server A or server B, the cache maintained by the ProductManager component must always be synchronized with the database; for example, If ProductManager on server A updates its cache and consequently the underlying physical data, then ProductManager on server B should reflect these changes in its own cache. In other words, changes to one instance of the cache should be replicated to all other cache instances. This is the same exact concept as database replication except that we dealing here with caches rather than with databases.

Here are some terms that are useful when describing cache replication strategies:

Which topology to use often depends on system configuration. Some common topologies include:

Irrespective of the used cache topology, it is beneficial to manage cache replication in a generic fashion outside application and data access code. This allows you to use a versatile and reusable system that is not tied to a particular application of topology. Cache replicator allows you to manage cache replication in a generic fashion outside application and data access code. It is entirely contained and can be used to coordinate replication across heterogeneous cache implementations. 

Structure & UML

The following figure illustrates the static structure for the Cache Replicator :

ICache interface is implemented by both ConcreteCache and ReplicatedCache. In this design, ReplicatedCache acts as a Decorator since it implements ICache and delegates all its operations to ConcreteCache. In addition, ReplicatedCache maintains a list of ICacheUpdateObservers that it notifies whenever it delegates a Put or Remove operation. CacheReplicator is a special implementation of ICacheUpdateObserver that updates another Cache instance when a ReplicatedCache notifies it. In other words, CacheReplicator serves as the notification channel from a source cache to a target cache

You can also implement ICacheUpdateObserver to do anything related to cache update operations. For example, if you want to log all cache operations, you can implement ICacheUpdateObserver in such a way (not shown above) that it writes to the log whenever notified by ReplicatedCache

The following figure illustrates the sequence diagram when a client issues a ReplicatedCache.Put operation.

The ReplicatedCache instance delegates the call to its local ConcreteCache implementation. Next, ReplicatedCache notifies each registered CacheReplicator by calling its EntryAdded method. Each CacheReplicator responds by invoking the corresponding operation on another Cache instance.




Use this pattern when:


Strategies / Variants

Recall that CacheReplicator's role in this pattern is to serve as the notification channel from a source cache to a target cache. If the participating caches exist entirely within the same process, then you can implement notifications using .NET events or asynchronous delegates. If CacheReplicator needs to sends notifications to other cache instances that live outside the process or on another machine, then cross-process (.NET Remoting) or cross-machine (.NET Remoting/messaging/queueing) communication is required. It also feasible for replicated caches to exist on heterogeneous platforms (Unix, Linux, etc) provided that the CacheReplicator implementation takes care of the required conversions for the cached data.

The source cache must always be a ReplicatedCache instance that issues update notifications, but the target can be any ICache implementation. If, according to the cache topology, a target cache is also responsible for delegating cache changes to other caches (like the central cache  topology), attach the CacheReplicator to the target ReplicatedCache. If the target is not responsible for delegating changes to other caches, then you can attach the CacheReplicator directly to the appropriate ConcreteCache.



Related Patterns