Introduction
How many times did you find yourself stuck in not-at-all-performing web application after months of development and tremendous effort? How many times did you wonder why your client should keep you as his expert if you cannot deliver what seems to common users as a standard of fast and fastest? How many times did you hear the terrible comparison to Google and Facebook? Let me tell you how my client turned out things:
I was working on a web application with heavy processing and filtering due to many business rules and UI requirements. Add to that a third party provider with outdated technologies to whom speed means 15 years of work to throw to garbage and restart. My application was not that fast, sometimes a request took about 6 to 8 seconds to get processed, business rules verified, filtered and formatted response. It was just unacceptable to my client. I was told that it’s possible if Google did it. Facebook too, did it by the way. I didn't explain to my client how heavy and big the hardware is and muz of servers behind that speed. I just responded that it’s possible to do better and I promised to do so having Redis in my mind.
So, before getting deep into Redis, let me tell a bit about NoSql.
Most developers are accustomed to relational databases. The Data Driven Development fashion or Domain Driven one (as in Entity Framework Code First or again in Fluent API NHibernate), the concepts of relational databases are still the same. The NoSql on the other hand brought the document fashion data store. The popular ones among the .NET community are MongoDb, RavenDb and Redis. I already wrote a how-to about MongoDb that you may find here. I used it to log important activities, errors and exceptions, etc.
Again in the NoSql world, the concepts are pretty much the same for all popular databases. Basically it is JSon documents stored somewhere on your machine or on a server with sort of .NET client or driver to access it for manipulation. The great thing about NoSql resides in the fact that it resolved a major flaw when using relational databases combined with OO languages as C# or Java: impedance mismatch.
Redis is just the same as any NoSql database. But it stands out by the fact that it lives in memory. It's an in memory NoSql database.
In a nutshell, Redis gives you an incredible ability to cash your objects state and consequently speed up your application. Sometimes, you can get your application 8 to 10 times speeder. This is not a joke and you don’t need to have the Google or Facebook infrastructure behind. If you need to learn more about the idea behind Redis and its history, you could check out the web. There is a lot of literature about it.
Redis stands for Remote Dictionary Service and it's exactly that. It's a key value store just as a C# dictionary object. So let's see how we can use that:
First, let's get Redis installed and running by following these steps:
- Go to redis.io and fetch the win64 version and download it (it goes without saying that the version you need depends on your system)
- Copy the content to a new folder called Redis (you can name it as you wish!)
- Click on redis-server.exe to run the server
- Click on redis-client.exe to run client command utility
Now, let's try some basic commands to make sure everything is set up correctly. In the client commandline, do the following:
- Type:
set azul "hello world"
to add an entry and you should get back an ok. This means you have an entry with a key: azul and value: "hello world!" (by the way, azul is a greeting in kabyle language) Get azul
to fetch the value and you get back the value hello world
Delete azul
will remove the entry
As far as Redis is a dictionary, it's possible to give a key and then a value to store as follows:
Set schedule:1 "{'origin':'Montreal','destination':'Toronto'}"
In the previous example, the value is JSon object. This shows you that you can add a complex object to Redis. But there is more than this to the story because there are 5 data types you can rely upon to meet your needs.
You could also identify the key as follows:
Set schedule: id 1
For multiple set
and get
, use instead mset
and mget
commands. I will not cover more than this about commands. You can just check the documentation and play with it as you please.
Behind the Scenes
What we’ve done so far is awesome and an out-of-the-box thing. But behind the scenes, Redis client sends commands to server over Redis protocol. The server executes the commands upon the data in memory and sends back the response.
There is nothing more than this, no foreign keys involved, no indexes, no tables, no even documents. Of course, you could go further and store the data on disk, but I will not cover it here.
Redis as Service
You could use Redis on a physical machine, virtual machine or as a Cloud service. Many providers as Digital Ocean and lately Windows Azure offer the service. We will choose Digital Ocean (mainly for the price and I think the redis service on Azure is a little bit expensive) and set up from there.
To connect to Digital Ocean, we use PuTTY over ssh (secure way to connect there). Download PuTTY and configure the IP address you get from DO droplet you created (the droplet is your linux machine you create on DO). Then PuTTY open up and log in with root account and the password you got from DO. To make sure you are up to date with your Linux machine, run the following command: apt-get update
(Linux folks are all excited now!!!!)
Now you are or should be up to date. Then execute apt-get install build-essential
to get any missing utility for your Linux server. You are done. There are more detailed step by step blogs about this out there. I have to admit here that I had some hard time actually to get all things set up since I am not that familiar with the Linux world.
In Visual Studio
In home sweet home, add an MVC project and use Nuget Package Manager to add Servicestack.redis. With this, you get a way to connect to Redis and ready to do some fun stuff.
To get to Redis in a controller and get a list of your cached object, you need to do as follows:
using(IRedisClient client = RedisClient)
{
var scheduleClient= client.GetTypedClient<Schedule>();
var schedules = scheduleClient.GetAll();
}
This is an extremely fast operation even if you have a lot of objects. It’s a good idea to cache in Redis a ready to use data to avoid even the business processing (applying rules and specifications or any other filtering and formatting) when possible.
The many round-trips to database to get back some objects (always the same) are another good candidate to Redis. In general, all the stuff we used to cache in repositories (browse cached repository pattern for more details about this) are candidates to go to Redis. This is how you can get result fast, very fast to improve the overall performance of your web application.
Note that scheduleClient
will expose a lot of functions to add, append, remove and use lists, hashes, etc. Give it a try to explore more…
You could also set up your Redis client to give you a glimpse (without Glimpse -;)) of what is going on behind the scenes by adding: monitor command
(in the same place where we added the azul entry at the beginning).
There is also one thing I should mention here before the entire anti-HelloWorldish app style (I admit I am one of them!) warriors jump up to the sky: it’s not a good idea to go from your controllers to your database (let it be Redis!) and if this sounds weird to you, I think you need to read some stuff about design and architecture. I don’t understand the Microsoft instructors that instruct user that by adding an MVC project you are ready to build a great business web application. Because it’s not.
However, here is an example of how to add an object, in this case a schedule:
public class Schedule
{
public int Id {get; set;}
public string Origin {get; set;}
public string Destination {get; set;}
}
using(IRedisClient client = RedisClient)
{
var scheduleClient= client.GetTypedClient<Schedule>();
var schedule= new Schedule
{
Id= scheduleClient.GetNextSequence(),
Origin ="Montreal",
Destination = "Quebec"
}
var schedules = scheduleClient.Store(schedule);
}
Since Redis is a caching service, it is possible to expire an entry by setting a timeout to it. You could even reverse that by removing the timeout.
This is just an introductory how-to to Redis to give you a hint about one possible way to improve the performance of your web application. Redis may give you, in some circumstances, the rewards your client or boss lack to give you as recognition for your passion of building reliable softwares.
Hope this will help somebody!