Azure AppFabric Caching Service

UPDATE 4/30/2011 – The Azure AppFabric Caching service has been released and the SDK can be downloaded from here. The service is available in all Windows Azure datacenters. There are not many differences between the CTP and production version. I have updated this post to use the production version.

The Azure AppFabric Caching Service was released into the Azure AppFabric Labs at PDC 10. This service makes available to the Azure Platform many of the features of the Windows Server AppFabric Caching Service (formerly known as Velocity). The Azure AppFabric Caching Service supports the centralized caching of data and the local caching of that data. It also provides pre-built session and page-state providers for web sites. These can be used with only configuration changes to an existing web site. (This post doesn’t go into that feature.)

Wade Wegner has a great PDC 10 presentation introducing the Azure AppFabric Caching Service. He also participates in a very interesting conversation with Karandeep Anand for Channel 9. Wade Wegner and Karandeep Anand have an article on the Azure AppFabric Caching service in MSDN Magazine, The Windows Azure Platform Training Kit (April 2011) contains a hands-on lab for the Azure AppFabric Caching Service. This lab is included in the Windows Azure Platform Training Course. This post complements an earlier post on another Azure AppFabric Labs feature: Durable Message Buffers.

Gartner recently released a research note on Windows Azure AppFabric: A Strategic Core of Microsoft’s Cloud Platform. In its discussion of the Azure AppFabric Caching Service the report points out that the “Gartner Reference Architecture for Application Platforms for Cloud Computing” includes distributed caching as an essential element in delivering the scalability and performance expected of advanced cloud environments.

The monthly cost of the Azure AppFabric Caching depends on the cache size and varies from $45 for 128 MB to $325 for 4GB. Microsoft is offering an introductory free period until August 2011. There is an interesting discussion of cache pricing on an Azure Forum thread.

The Azure AppFabric Caching Service appears to be a very powerful and easy-to-use addition to the Azure Platform. It will be interesting to see how the Azure AppFabric Caching Service develops over the coming months – but it has got off to a really solid start.

AppFabric Caching

The Windows Server AppFabric Caching Service runs on a cluster of servers that present a unified cache to the client. This service requires IT support to manage and configure the servers. These clusters can be quite large – the documentation, for example, describes the cache management needs of a cluster in the range of 50 cache servers. This IT need disappears in Azure AppFabric Caching since Microsoft handles all service management.

In Windows Server AppFabric Caching Service it is possible to create named caches and provide different configuration characteristics to each cache. For example, one cache with rarely changing data could have a very long time-to-live configured for cached data while another cache containing more temporary data could have a much shorter time-to-live. Furthermore, it is possible to create regions on a single node in the cache cluster and associate searchable tags with cache entries. Neither of these features are implemented in Azure AppFabric Caching which supports only the default cache (named, unsurprisingly, default).

The Windows Server AppFabric Caching Service supports cache notifications which cache clients can subscribe to and receive notification when various operations are performed on the cache and the items contained in it. This feature is not supported in Azure AppFabric Caching Service.

Both the Azure and the Windows Server AppFabric Caching Service use various techniques to remove data from the cache automatically: expiration and eviction. A cache has a default timeout associated with it after which an item expires and is removed automatically from the cache. This default timeout may be overridden when items are added to the cache. The local cache similarly has an expiration timeout.  The Windows Server AppFabric Caching Service supports notification-based expiration but that is not implemented in the Azure AppFabric Caching Service. Eviction refers to the process of removing items because the cache is running out of memory. A least-recently used algorithm is used to remove items when cache memory comes under pressure – this eviction is independent of timeout.

The Azure and Windows Server AppFabric Caching Services support two concurrency models: optimistic and pessimistic. In optimistic concurrency, a version number is provided when an item is retrieved from the cache. This version number can be provided when the item is updated in the cache and the update fails if an old version number is provided. In pessimistic concurrency, the item is locked when it is retrieved from cache and unlocked when it is no longer needed. However, pessimistic concurrency assumes that all clients obey the rules regarding locks because regardless of any current lock an item can be updated by an operation not using locks.

Note that the Azure AppFabric Caching service is a shared system subject to quotas on cache size, transactions, bandwidth and concurrent connections. The quota are per hour, and service use is throttled once a quota has been reached. The AppFabric Customer Advisory Team has a post explaining the quotas.

Configuring the Azure AppFabric Caching Service

Note that links to classes in this and subsequent sections are to the documentation for the Windows AppFabric Caching Service. Since the intent is that they use the same API this should be a reasonable proxy until the Azure AppFabric Caching Service documentation is available online.

The documentation for Windows AppFabric Caching Service uses the expression cache cluster to refer to the central (non-local) cache. In this and subsequent sections I use the alternate term AppFabric cache for the central cache to emphasize the fact that we don’t care about its implementation.

The DataCacheFactoryConfiguration class is used to configure the Azure AppFabric Cache. It is declared:

public class DataCacheFactoryConfiguration : ICloneable {
// Constructors
public DataCacheFactoryConfiguration(String clientName);
public DataCacheFactoryConfiguration();

// Properties
public TimeSpan ChannelOpenTimeout { get; set; }
public Boolean IsCompressionEnabled { get; set; }
public DataCacheLocalCacheProperties LocalCacheProperties { get; set; }
public Int32 MaxConnectionsToServer { get; set; }
public DataCacheNotificationProperties NotificationProperties { get; set; }
public TimeSpan RequestTimeout { get; set; }
public DataCacheSecurity SecurityProperties { get; set; }
public IEnumerable<DataCacheServerEndpoint> Servers { get; set; }
public DataCacheTransportProperties TransportProperties { get; set; }

// Implemented Interfaces and Overridden Members
public Object Clone();
}

When an Azure AppFabric Caching Service service is configured, the Azure AppFabric Portal provides a cache endpoint and an authentication token. The Servers property specifies the cache endpoint. The authentication token is provided via the SecurityProperties property. Note that Notification is not supported by the Azure AppFabric Caching Service so that NotificationProperties should not be used. LocalCacheProperties specifies the configuration of the local cache. It can be set to null if the local cache is not required. The default timeout for the (Azure) AppFabric cache is 10 minutes.

The LocalCacheProperties property is of type DataCacheLocalCacheProperties declared:

public class DataCacheLocalCacheProperties {
// Constructors
public DataCacheLocalCacheProperties();
public DataCacheLocalCacheProperties(Int64 objectCount,
TimeSpan defaultTimeout,
DataCacheLocalCacheInvalidationPolicy invalidationPolicy);

// Properties
public TimeSpan DefaultTimeout { get; }
public DataCacheLocalCacheInvalidationPolicy InvalidationPolicy { get; }
public Boolean IsEnabled { get; }
public Int64 ObjectCount { get; }
}

DefaultTimeout is the default timeout for the local cache. InvalidationPolicy specifies the invalidation policy for the local cache and must be DataCacheLocalCacheInvalidationPolicy.TimeoutBased since notification-based expiration is not supported in Azure AppFabric Labs. IsEnabled indicates whether or not the local cache is enabled for the cache client. ObjectCount specifies the maximum number of items that can be stored in the local cache. Items are added to the local cache when they are retrieved from the AppFabric cache. There is no way to add items to the local cache independently of the AppFabric cache.

The DataCacheFactoryConfiguration is passed into a DataCacheFactory constructor to create the DataCache object used to interact with the cache. DataCacheFactory is declared:

public sealed class DataCacheFactory : IDisposable {
// Constructors
public DataCacheFactory(DataCacheFactoryConfiguration configuration);
public DataCacheFactory();

// Methods
public DataCache GetCache(String cacheName);
public DataCache GetDefaultCache();

// Implemented Interfaces and Overridden Members
public void Dispose();
}

The DataCacheFactory() constructor reads the cache configuration from the app.config file. In the Azure AppFabric Caching Service GetCache(String) can be used with the parameter “default” or, more simply, GetDefaultCache() can be used to retrieve the DataCache object for the default (and only) cache.

The following is an example of cache configuration:

private DataCache InitializeCache()
{
Boolean isSslEnabled = true;
String hostName = “SERVICE_NAMESPACE.cache.appfabriclabs.com”;
String authenticationToken = @”BASE64 AUTHENTICATION TOKEN”;
Int32 cachePort = isSslEnabled ? 22243 : 22233;
Int64 sizeLocalCache = 1000;

List<DataCacheServerEndpoint> server =
new List<DataCacheServerEndpoint>();
server.Add(new DataCacheServerEndpoint(hostName, cachePort));

DataCacheLocalCacheProperties localCacheProperties =
new DataCacheLocalCacheProperties(sizeLocalCache, TimeSpan.FromSeconds(60),
DataCacheLocalCacheInvalidationPolicy.TimeoutBased);

DataCacheFactoryConfiguration dataCacheFactoryConfiguration =
new  DataCacheFactoryConfiguration()
{
ChannelOpenTimeout = TimeSpan.FromSeconds(45),
IsCompressionEnabled = false,
LocalCacheProperties = localCacheProperties,
MaxConnectionsToServer = 1,
// NotificationProperties = null, //not supported in Azure Caching
RequestTimeout = TimeSpan.FromSeconds(45),
SecurityProperties = new DataCacheSecurity(
CreateSecureString(authenticationToken), isSslEnabled),
Servers = server,
TransportProperties = new DataCacheTransportProperties()
{
MaxBufferSize = 100000
}
};

DataCacheFactory myCacheFactory =
new DataCacheFactory(dataCacheFactoryConfiguration);
dataCache = myCacheFactory.GetCache();
//dataCache = myCacheFactory.GetCache(“default”);
return dataCache;
}

This method creates the cache configuration and uses it to create a DataCache object which it then returns. The configuration provides for only a 60s expiration timeout for the local cache which contains at most 1,000 items.

Note that the February 2011 release changed the constructor parameter for DataCacheSecurity from String to SecureString. In his post pointing this out, Wade Wegner used the following code to convert a String token to a SecureString token:

static private SecureString CreateSecureString(String token)
{
SecureString secureString = new SecureString();
foreach (char c in token)
{
secureString.AppendChar(c);
}
secureString.MakeReadOnly();
return secureString;
}

DataCache

DataCache is the core class for handling cached data. The following is a very truncated version of the DataCache declaration:

public abstract class DataCache {
// Properties
public Object this[String key] { get; set; }

// Methods
public DataCacheItemVersion Add(String key, Object value);
public Object Get(String key);
public Object GetAndLock(String key, TimeSpan timeout,
out DataCacheLockHandle lockHandle);
public DataCacheItem GetCacheItem(String key);
public Object GetIfNewer(String key, ref DataCacheItemVersion version);
public DataCacheItemVersion Put(String key, Object value);
public DataCacheItemVersion PutAndUnlock(String key, Object value,
DataCacheLockHandle lockHandle);
public Boolean Remove(String key);
public void ResetObjectTimeout(String key, TimeSpan newTimeout);
public void Unlock(String key, DataCacheLockHandle lockHandle);
}

Each of these methods comes in variants with parameters supporting optimistic and pessimistic concurrency. There are variants with tags which are not supported in the Azure AppFabric Caching Service. The tags themselves are actually saved with the item and can be retrieved with the item – but searching is not functional because of the lack of region support.

The Add() methods add a serializable item to the AppFabric cache. One variant allows the item to have a non-default expiration timeout in the AppFabric cache.

The Get() methods retrieve an item from the cache while the GetAndLock() methods do so for the pessimistic concurrency model. If the item is present in the local cache it will be retrieved from these otherwise it will be retrieved from the AppFabric cache and added to the local cache. The objects retrieved with these methods need to be cast to the correct type. GetCacheItem() retrieves all the information about the item from the AppFabric cache. GetIfNewer() retrieves an item from the AppFabric cache if a newer version exists there.

The Put() methods add an item to the AppFabric cache while the PutAndUnlock() methods overwrite an existing item in the pessimistic concurrency model.

The Remove() methods remove an item from the AppFabric cache.

ResetObjectTimeout() modifies the timeout for a specific item in the AppFabric cache.

The Unlock() methods release the lock on an item managed in the pessimistic concurrency model.

The Item property (this[]) provides simple read/write access to the item – similar to an array accessor.

The DataCacheItem class provides a complete description of an item in the AppFabric cache and is declared:

public sealed class DataCacheItem {
// Constructors
public DataCacheItem();

// Properties
public String CacheName { get; }
public String Key { get; }
public String RegionName { get; }
public ReadOnlyCollection<DataCacheTag> Tags { get; }
public TimeSpan Timeout { get; }
public Object Value { get; }
public DataCacheItemVersion Version { get; }
}

CacheName is the name of the AppFabric cache, i.e. default. Key is the unique identifier of the item. RegionName is the name of the region containing the item. Note that regions are not supported in Azure AppFabric Caching Service but this property will have a more-or-less random value in it. The Tags property contains all the tags associated with the item. Tags are not supported by the Azure AppFabric Caching Service. In fact, the tag methods appear to work but their functionality is limited by the lack of support for regions. The Timeout property specifies for how much longer the item will remain in the AppFabric cache. The Value is the actual value of the item and needs to be cast to the correct type. Version specifies the current AppFabric version of the item as used for optimistic concurrency.

Cache Aside

The cache aside programming model should be used with the Azure AppFabric Caching Service. If the data is in the cache it is used. Otherwise, it is retrieved from its source, added to the cache and then used. This is necessary because it can never be guaranteed that cached data has not been expired or evicted from the cache.

Examples

The following adds three items to the AppFabric cache:

private void AddEntries()
{
dataCache.Add(“Malone Dies”, “Samuel Beckett”);
dataCache.Put(“Molloy”, “Samuel Beckett”, TimeSpan.FromMinutes(1));
dataCache["The Unnamable"] = “Samuel Beckett”;
}

The Put() invocation also reduces the expiration timeout to 1 minute from the default 10 minutes.

The following retrieves three items from the cache:

private void GetEntries()
{
String ulysses = dataCache.Get(“Molloy”) as String;
String molloy = dataCache["Malone Dies"] as String;
DataCacheItem dataCacheItem2 = dataCache.GetCacheItem(“The Unnamable”);
}

The first two calls use the local cache if the items are present there. The final call always uses the AppFabric cache.

The following removes three items from the AppFabric cache:

private void ClearEntries()
{
dataCache.Remove(“Malone Dies”);
dataCache["Molloy"] = null;
dataCache["The Unnamable"] = null;
}

The following demonstrates optimistic concurrency:

private void OptimisticConcurrency()
{
String itemKey = “Malone Dies”;
DataCacheItem dataCacheItem1 = dataCache.GetCacheItem(itemKey);
DataCacheItem dataCacheItem2 = dataCache.GetCacheItem(itemKey);
dataCache.Put(itemKey, “A novel written by Samuel Beckett”);
// Following fails with invalid version
dataCache.Put(itemKey, “Samuel Beckett”, dataCacheItem2.Version);
}

The second Put() fails because it uses an older version of the item than the one updated by the first Put().

The following demonstrates pessimistic concurrency:

private void PessimisticConcurrency()
{
String itemKey = “Ulysses”;
dataCache[itemKey] = “James Joyce”;

DataCacheLockHandle lockHandle1;
DataCacheLockHandle lockHandle2;
String ulysses1 = dataCache.GetAndLock(itemKey, TimeSpan.FromSeconds(5),
out lockHandle1) as String;
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(6));
String ulysses2 = dataCache.GetAndLock(itemKey, TimeSpan.FromSeconds(5),
out lockHandle2) as String;
// following works regardless of lock status
//dataCache.Put(itemKey, “James Augustine Joyce”);
dataCache.PutAndUnlock(itemKey, “James Augustine Joyce”, lockHandle2);
}

In this example the lock handle acquired in the first GetAndLock() is allowed to expire. The lock handle acquired in the second GetAndLock() is formally unlocked by PutAndUnlock() which also changes the value of the item. Note that pessimistic concurrency can be overridden by methods that are not lock aware as alluded to in the final comment.

UPDATE 2/10/2011: Updated to Feb 2011 release including change to SecureString in DataCacheSecurity constructor.

About these ads

About Neil Mackenzie

Azure Architect at Satory Global.
This entry was posted in Caching, Windows Azure and tagged , , . Bookmark the permalink.

6 Responses to Azure AppFabric Caching Service

  1. Pingback: Windows Azure AppFabric Applications | Convective

  2. Pingback: How to use a WCF custom channel to implement client-side caching in a Windows Azure-hosted application | AppFabric CAT

  3. Pingback: Windows Azure and Cloud Computing Posts for 8/5/2011+ - Windows Azure Blog

  4. Lee says:

    the concept of caching is not a new concept any more. more and more companies are using distributed caching product which were facing performance and scalability problems with their asp.net app. the standard asp.net cache was unable to provide performance and scalablity to the app due to its stand alone and in process nature. this was the reason why MS jumped into the field of distributed caching, but still AppFabric has to come a long way to compete with products like NCache. here is good read about the comparison of these distributed cache providers.
    http://distributedcaching.blog.com/2011/05/26/ncache-features-that-app-fabric-does-not-have/

  5. Pingback: Working around Windows Azure AppFabric Cache timing out with large amounts of data « Bob the Goblin

  6. Pingback: How to use a WCF custom channel to implement client-side caching in a Windows Azure-hosted application - Paolo Salvatori's Blog - Site Home - MSDN Blogs

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s