Saturday 18 February 2017

Using Redis as a Data Caching Server

Everyone knows how important caching is in computing. We are surrounded by caching managers here, there and everywhere. You've got your CPU caching in the form of L1 and L2 cache which stores the next bit of data the CPU needs. GPUs have a cache. All hard drives come equipped with an on-board cache. Database servers heavily cache your most used queries and query plans, web servers cache the most used data and web clients (browsers) cache client side data.

Basically, caching is everywhere.

Why am I mentioning this? Well, recently I have been redesigning a framework that plans to make use of cached data to save trips to the database and Redis looks very enticing.

But what's the cost/impact of not using a cache?

Well, I found this great link "Latency Numbers Every Programmer Should Know", which orders the latency numbers of accessing the "CPU cache" all the way up to connecting to a computer over the open internet.

The numbers shouldn't surprise you. Basically accessing memory is wicked fast! (It can be referenced in 100ns). If you have the data in memory versus retrieving it from the database on another server it's a no-brainer! - Memory wins every time.

That's where Redis comes in. - It's a fast in-memory data cache/NoSQL database.

It's an open source server software and they have a client for every programming language imaginable. It's also used by websites like Twitter, GitHub, Stack Overflow, etc.

Installation (on Windows)

The download pages of Redis explain that the "Microsoft Open Tech group" support the windows port of Redis. It's available to download via nuget here. Just: "Install-Package Redis-64"

Incidently, it looks like Azure allows you to setup a Redis cache on their service. I wonder if they are using the same version of Redis they are hosting on nuget?!

When you run the server from the command line you will see the Redis logo and that the server is accepting connections on port 6379 (the default port).

This runs the Redis server in interactive mode.

To install Redis as a windows service run this command redis-server --service-install redis.windows.conf --loglevel verbose. To uninstall the service run this command: redis-server --service-uninstall

You can then go and start Redis as a windows service

That's it! The server is installed!

ServiceStack.Redis Client

Once you have got the server installed, the next thing you will need to do is download a client. The best client for C# is ServiceStack.Redis

So what's the code look like?

Well, it's nice and simple. Just what we like. For example the following code adds some data to the cache, then retrieves it later on.

using ServiceStack.Redis;

class Program
{
    static void Main(string[] args)
    {
        string someOrder = "some data to cache";

        // Store some Data
        using (RedisClient client = new RedisClient("127.0.0.1", 6379))
        {
            client.SetValue("order:1", someOrder);
        }

        // Later on! - Lets get some data from the cache.
             
        using (IRedisClient client = new RedisClient("127.0.0.1", 6379))
        {
            var result = client.GetValue("order:1");
        }
    }
}

Expiring Data

As we all know, one important aspect of a cache is knowing when to let go of the cached data. This can give you headaches if you hold on to data too long. This is application specific and you will need to understand the time limits for when certain types of data goes stale.

Here's a more complicated example that serialises a class as well as expiring the data after 10 seconds.

using ServiceStack.Redis;
class Person
{
    public string Name { get; set; }
    public int Age { get; set; }

    public Person(string n, int a)
    {
        Name = n; Age = a;
    }
}

class Program
{
    static void Main(string[] args)
    {
        Person person1 = new Person("Rick", 45);
        Person person2 = new Person("Morty", 18);

        string jsonString = "";

        int hours = 0, mins = 0, secs = 10;
        TimeSpan expireIn = new TimeSpan(hours, mins, secs);

        // Store some Data
        using (RedisClient client = new RedisClient("127.0.0.1", 6379))
        {
            jsonString = Newtonsoft.Json.JsonConvert.SerializeObject(person1);
            client.SetValue("person:1", jsonString, expireIn);

            jsonString = Newtonsoft.Json.JsonConvert.SerializeObject(person2);
            client.SetValue("person:2", jsonString, expireIn);
        }

        // Later on! - Lets get some data from the cache.
             
        using (IRedisClient client = new RedisClient("127.0.0.1", 6379))
        {
            var result = client.GetValue("person:2");
            
            if ( result != null)
            {
                var pTemp = Newtonsoft.Json.JsonConvert.DeserializeObject(result);
            }
        }

        // Much Later on (after 10 secs)! - Lets get some data from the cache.
        Thread.Sleep(1000 * 12);

        using (IRedisClient client = new RedisClient("127.0.0.1", 6379))
        {
            var result = client.GetValue("person:2");

            // The result will be null because more than 10 secs have elapsed
            if (result != null)
            {
                var pTemp = Newtonsoft.Json.JsonConvert.DeserializeObject(result);
            }
        }
    }
}

Wrapping Up!

There's a lot more to Redis than I have mentioned here. It has a full suite of commands and can be used in many other ways apart from a cache - but it makes a great cache manager!


Contact Me:  ocean.airdrop@gmail.com

Popular Posts

Recent Posts

Unordered List

Text Widget

Pages