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

Sunday 12 February 2017

Code and Music

Do you listen to music when you code?

I do.

For me, there is no better experience of falling into a code-hole while being wisked away by a backing track of your liking.

I find the two compliment each other.

If you have a sufficiently meaty problem and an inkling of how you're going to solve it, music can sweep away time.

You tumble down that code-hole and before you know it, you look up and a couple of hours have passed.

Something happens in our brains, where your logic and reasoning about a problem develops to the point where you get a nice flow going. It's hard to explain but it happens.

I am in no way precious about what type of music I listen to. In fact I listen to a lot of different genres but I find nothing compliments coding better than a DJ set.

I love music (who doesn't). I collect music. I grew up being fed and watered on all types of dance music genres and back in the day, listening to the BBC Essential Mix was a staple! - In today's landscape music has never been more accessible with podcasts, youtube, soundcloud, mixcloud etc. There is so much fuel out there to use to code to.

My takeaway? Let the music play, and don't forget to turn it up to 11.


Contact Me:  ocean.airdrop@gmail.com

Sunday 5 February 2017

SeriLog & Application Diagnostic Logging

Show me an application that doesn't log anything and i'll show you an application which is hard to debug.

Every application we write should have a healthy sprinkling of diagnostic logging embedded throughout its logic. A trace to show us what's happening on the inside from the outside. In the past, I've hand-rolled my own bespoke logging classes to output either to file, database or simply console.

Not any more!

The problem has been solved. It's been done. There are libraries out there like Log4Net or Nlog

But from now on, I intend to standardise all my C# code to use SeriLog.

SeriLog is an example of a library where so many developers have poured in so much time that any home grown library cannot compete.

Why waste your time? Just "nuget" it into your project and be done. Move on.

Why is it so cool?

Because it's simple. And because it supports many, many outputs. They call them sinks and there is a sink for everything as you can see in the image above.

But the real cool part is that you can pass a data model to SeriLog and it will serialise the properties in JSON format.

Want to see some sample code? The github pages have plenty of samples there but the code sample below demonstrates how SeriLog logs to:

  • The screen
  • A rolling log file on disk
  • And a database table
using Serilog;

namespace OceanAirdrop
{
    class SomeModel
    {
        public int UserId { get; set; }
        public string Name { get; set; }
        public DateTime BirthDate { get; set; }
    }

    public class SeriLogger
    {
        public static void Main(string[] args)
        {
            string connName = "db-connection-string";

            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Debug()
                .WriteTo.LiterateConsole()                 
                .WriteTo.RollingFile("AppLogs\\SomeCoolApp-{Date}.txt")
                .WriteTo.MSSqlServer(connName, "some_cool_app_log")
                .CreateLogger();

            try
            {
                Log.Information("Some important log information!");

              var someData = new User { UserId = 256, Name = "Ocean Airdrop", BirthDate = DateTime.Now };

                Log.Information("Some more logging: {@User}", someData);
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Something went kaboomski!");
            }
        }
    }
}

Contact Me:  ocean.airdrop@gmail.com

Popular Posts

Recent Posts

Unordered List

Text Widget

Pages