Export (0) Print
Expand All

Caching data in Azure Redis Cache

Updated: November 24, 2014

.NET applications can use the StackExchange.Redis cache client to access their Azure Redis Cache instances. This topic provides examples of common programming tasks when working with caches in Azure Redis Cache using the StackExchange.Redis client.

noteNote
For information about working with Azure Redis Cache from non-.NET clients, see Develop in other languages for Azure Redis Cache.

For more information about StackExchange.Redis, see the StackExchange.Redis github page and the StackExchange.Redis cache client documentation.

In this topic

Connect to the cache using the ConnectionMultiplexer class

In order to programmatically work with a cache, you need a connection to the Azure Redis Cache service instance that hosts the cache. These connections are managed by the ConnectionMultiplexer class.

noteNote
Add the following using statement to the top of any file from which you want to access the cache.

using StackExchange.Redis;

If this namespace doesn’t resolve, be sure that you have configured your application for caching, as described in Configure .NET cache clients for Azure Redis Cache.

Note that the StackExchange.Redis client requires .NET Framework 4 or higher.

To connect to an Azure Redis Cache instance, call the static ConnectionMultiplexer.Connect method and pass in the endpoint and key, as shown in the following example.

ConnectionMultiplexer connection = ConnectionMultiplexer.Connect("contoso5.redis.cache.windows.net,ssl=true,password=...");
ImportantImportant
ConnectionMultiplexer is designed to be shared and reused throughout your client application, and does not need to be created on a per operation basis. If you create an instance and connect every time you make a call to the cache, performance will be degraded. Additionally, Azure Redis Cache has a connection limit of 10,000 connected clients. If many ConnectionMultiplexer instances are connected rapidly, this limit could be reached.

One approach to sharing a ConnectionMultiplexer instance in your application is to have a static property that returns a connected instance, similar to the following example. This provides a thread-safe way to initialize only a single connected ConnectionMultiplexer instance. In this example abortConnect is set to false, which means that the call will succeed even if a connection to the Azure Redis Cache is not established. One key feature of ConnectionMultiplexer is that it will automatically restore connectivity to the cache once the network issue or other causes are resolved.

private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
{
    return ConnectionMultiplexer.Connect("contoso5.redis.cache.windows.net,abortConnect=false,ssl=true,password=...");
});

public static ConnectionMultiplexer Connection
{
    get
    {
        return lazyConnection.Value;
    }
}

If you don’t want to secure your cache/client communication with SSL, simply pass in the endpoint and key, or set ssl=false.

ImportantImportant
The non-SSL port is disabled by default for new caches. For more information about enabling the non-SSL port, see the Access Ports section in the Configure a cache in Azure Redis Cache topic.

ConnectionMultiplexer connection = ConnectionMultiplexer.Connect("contoso5.redis.cache.windows.net,password=...");
noteNote
For more information about advanced connection configuration options, see StackExchange.Redis configuration model.

The cache endpoint, keys, and ports can be obtained from the Azure Management Portal Preview blade for your cache instance.

Azure Redis Cache Properties Azure Redis Cache Manage Keys

Once the connection is established, return a reference to the redis cache database by calling the ConnectionMultiplexer.GetDatabase method. The object returned from the GetDatabase method is a lightweight pass-through object and does not need to be stored.

IDatabase cache = Connection.GetDatabase();

// Perform cache operations using the cache object...
// Simple put of integral data types into the cache
cache.StringSet("key1", "value");
cache.StringSet("key2", 25);

// Simple get of data types from the cache
string key1 = cache.StringGet("key1");
int key2 = (int)cache.StringGet("key2");

Access primitive data types in the cache

The StackExchange.Redis client uses the RedisKey and RedisValue types for accessing and storing items in the cache. These types map onto most primitive language types, including string, and often are not used directly. Redis Strings are the most basic kind of Redis value, and can contain many types of data, including serialized binary streams,. and while you may not use the type directly, you will use methods that contain String in the name. The most common of these are the StringSet and StringGet methods.

// Simple put of integral data types into the cache
cache.StringSet("key1", "value");
cache.StringSet("key2", 25);

// Simple get of data types from the cache
string key1 = cache.StringGet("key1");
int key2 = (int)cache.StringGet("key2");

Note that while you don’t have to do any casting when using string, you do when using int.

noteNote
Unless you are storing collections or other Redis data types in the cache, StringSet and StringGet are the methods to use, even if your value is not a string.

When calling StringGet, if the object exists, it is returned, and if it does not, null is returned. In this case you can retrieve the value from the desired data source and store it in the cache for subsequent use. This is known as the cache-aside pattern.

// Simple cache-aside pattern
string value = cache.StringGet("key1");
if (value == null)
{
    // The item keyed by "key1" is not in the cache. Obtain
    // it from the desired data source and add it to the cache.
    value = GetValueFromDataSource();

    cache.StringSet("key1", value);
}

Specify the expiration of items in the cache

To specify the expiration of an item in the cache, use the TimeSpan parameter of StringSet.

cache.StringSet("key1", "value1", TimeSpan.FromMinutes(90));

In the previous example an interval of ninety minutes is shown. After ninety minutes, the item is removed from the cache. If a subsequent write operation is made, the specified expiration interval of the subsequent write operation begins at the time of the write.

Work with .NET objects in the cache

Azure Redis Cache can work with .NET objects as well as primitive data types, but before a .NET object can be cached it must be serialized. This is the responsibility of the application developer. This gives the developer flexibility in the choice of the serializer. In the following examples, an extension class to the StackExchange.Redis.IDatabase type is used along with the BinaryFormatter to simplify the serialization of objects before they are cached.

public static class SampleStackExchangeRedisExtensions
{
    public static T Get<T>(this IDatabase cache, string key)
    {
        return Deserialize<T>(cache.StringGet(key));
    }

    public static object Get(this IDatabase cache, string key)
    {
        return Deserialize<object>(cache.StringGet(key));
    }

    public static void Set(this IDatabase cache, string key, object value)
    {
        cache.StringSet(key, Serialize(value));
    }

    static byte[] Serialize(object o)
    {
        if(o == null)
        {
            return null;
        }

        BinaryFormatter binaryFormatter = new BinaryFormatter();
        using (MemoryStream memoryStream = new MemoryStream())
        {
            binaryFormatter.Serialize(memoryStream, o);
            byte[] objectDataAsStream = memoryStream.ToArray();
            return objectDataAsStream;
        }
    }

    static T Deserialize<T>(byte[] stream)
    {
        if(stream == null)
        {
            return default(T);
        }

        BinaryFormatter binaryFormatter = new BinaryFormatter();
        using (MemoryStream memoryStream = new MemoryStream(stream))
        {
            T result = (T)binaryFormatter.Deserialize(memoryStream);
            return result;
        }
    }
}

The RedisValue type can work directly with byte arrays, so when the Get helper method is called, it serializes the object into a byte stream, which is then cached. When the item is retrieved, it is serialized back into an object, and returned to the caller.

In the following example, an instance of an Employee object is serialized.

[Serializable]
class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }

    public Employee(int EmployeeId, string Name)
    {
        this.Id = EmployeeId;
        this.Name = Name;
    }
}
IDatabase cache = Connection.GetDatabase();

// Put an Employee object into the cache
cache.Set("Employee25", new Employee(25, "Clayton Gragg"));

// Retrieve it
Employee e2 = cache.Get<Employee>("Employee25");

// Retrieve it as an object
Employee e3 = (Employee)cache.Get("Employee25");
WarningWarning
If your object is not serializable you will receive an exception similar to the following when you try to serialize it.

Type 'SampleApplication.Employee' in Assembly SampleApplication, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.

Community Additions

ADD
Show:
© 2014 Microsoft