piotrwalat.net

Using Redis with ASP.NET Web API

3 comments

In this article I am going to show how to use Redis as a data store in a ASP.NET Web API application. I will implement a basic scenario that leverages ServiceStack.Redis library and its strongly typed Redis client, show how to model and store one-to-many relationships and how to use Web API dependency injection capabilities along with Autofac to inject repositories into controllers.

Client libraries

At the time of writing there are two popular and actively developed C# client libraries for Redis available:

Before making a choice I would suggest trying both of them and deciding which API and capabilities better suit your project.
BookSleeve has non-blocking (asynchronous) API, provides thread-safe connection object, while ServiceStack implementation provides JSON serialization, connection pool like client factory and uses convention to simplify POCO object persistence.

In this article I will use ServiceStack.Redis, but remember that BookSleeve has been proved in a big real-world web application and is also very capable.

Redis in a nutshell

If you are reading this article then very likely you already know what Redis is. If you are an experienced Redis user interested in ASP.NET Web API integration you can safely jump to the next part.

In order to use Redis efficiently and avoid potential pitfalls one needs to understand a little bit about how it works and how different it is from relational databases.I strongly recommend reading one of books or online materials available on the topic.

Simply put Redis is an in-memory key-value data store that supports durability.
In-memory and key-value sounds much like a memory cache – and indeed you can think of Redis as of a specialized and more advanced memory cache. Unlike other caches (such as memcached) Redis delivers richer feature set including things like sorted sets and even Lua scripting capabilities.

It’s main advantage over ‘traditional’ databases comes from the fact that it stores and retrieves data directly to / from operating memory – which means it is really fast.

Redis is simple and specialized – unlike relational databases it does not provide any table-like abstractions nor relational capabilities. Instead, it provides five fundamental data types along with specialized operations that can manipulate those types (stored values). This is why it is sometimes refered as a data structure server:

  • strings – the most basic and atomic type that can be used to store any data (integers, serialized POCO objects, etc.),
  • lists – lists of strings that are sored by insertion order,
  • sets – logical sets of strings,
  • hashes – maps between string-only keys and string values,
  • sorted sets – similar to sets, but each element is associated with a score that is being used to sort.

Examples of specialized commands:

  • strings – SET, INCR, APPEND, INCRBY, STRLEN, SETBIT,
  • lists – LPUSH, LPOP, LTRIM, LINSERT,
  • sets – SADD, SDIFF, SINTER, SUNION, etc.

Hopefully this should give you a basic feel for what Redis is about :)

Why would I use it?

Whether and how easily your application could benefit from Redis depends on its architecture, data volume, data complexity and experienced loads. When used correctly Redis can be bring major performance improvements and may help scale application out.

Here are some use cases I can think of:

  • as a main data store,
  • as one of multiple data stores, for example storing small, but frequently accessed information,
  • as a highly performant read-only view over your domain model,
  • as a cache.

Bearing in mind that Redis operates in memory, the first option is quite extreme and viable only if your data sets are small (or you can afford to have lots of RAM).
Because in this article I want to focus on ASP.NET Web API integration not architectural aspects I will choose this option.

Using Redis in a ASP.NET Web API application

I will use an empty ASP.NET Web API application as my starting point along with two third party libraries:

  • ServiceStack.Redis – C# Redis client,
  • Autofac – dependency injection container with Web API integration.

Obviously we will also need a working Redis server instance. If you don’t have one running already you can download Windows port provided by MS Tech. Please note that the port is not considered production ready yet (you need to use one of the official packages for that), but is good for development scenarios.

Model

For the sake of this example lets consider the following requirements:

  • the API should provide capability to store Clients, retrieve Client details and retrieve list of all Clients in the system,
  • Clients may place orders that consist of multiple items,
  • API should expose a list of N best selling items.

Here is how we could design the model:

Now let’s define repository contracts:

The implementation can look like this:

As you can see repositories expose specialized operations. We make use of Redis sorted set type to efficiently store and retrieve best selling products list.

It is worth noting how we implemented Customer -* Orders relation. We store customer’s orders (their ids) in a dedicated set so that they can be retrieved quickly without the need for pulling out entire Customer entity.

Client and connection lifecycle management

One of the challenges we will face is connection/client lifecycle management. As you may already know Web API ships with an extensible dependency injection mechanism that can be leveraged to inject and dispose dependencies on per request basis. Instead of writing custom IDependencyResolver implementation from scratch (which is also an option) we can use of of .NET DI libraries such as Ninject, StructureMap, Unity, Windsor or Autofac. The last one is my personal favorite and has good Web API integration that is why I am going to use it in this example.

ServiceStack.Redis ships with IRedisClient factories called client managers:

  • BasicRedisClientManager – client factory with load-balancing support,
  • PooledRedisClientManager – client factory with load-balancing and connection pooling – useful when working,
  • ShardedRedisClientManager – provides sharding of client connections using consistent hashing.

Because these classes are thread-safe we can use one factory instance across all requests.

We are using pooled connection manager as IRedisClientsManager implementation. Every time a request is made a new client instance will be retrieved, injected into repositories and disposed at the end of request.

Controllers

Now that we have repositories let’s implement the controllers – one for adding and retrieving the customers and one for managing orders.

That’s about it. We are now using Redis as our data store and dependencies should be auto-wired.

Source is available on Bitbucket.

Written by Piotr Walat

March 26th, 2013 at 10:27 am