Redis Cache

Overview

Redis is an open source key-value store that stores its data in memory (by default)

Supporting Source Code

https://github.com/hershbhasin/AzureSamples/tree/master/Caching

Availability For Windows

Redis Server for Windows

Officially, Redis is not supported on Windows

Paid Version

There is a paid version: Memurai for Windows

Memurai will have a tiered pricing scheme that will fit different users’ needs. The details are not available yet, but there will be a free edition aimed at development use.

Microsoft has a port for windows which is dated 2016

Microsoft Archive for Redis

This release is based on antirez/redis/3.2.1 plus some Windows specific fixes. It has passed all the standard tests but it hasn’t been tested in a production environment. Released on Jul 1, 2016

Also: https://github.com/ServiceStack/redis-windows

C++ Client for Windows

There c++ clients available for Radis on Windows (4 years old)

https://github.com/janeasystems/hiredis-windows

Dotnet Core client for Windows

Dotnet core clients are well supported. I have built POC using this client : https://github.com/ServiceStack/ServiceStack.Redis

Install Windows Version

Installing the version downloaded from Microsoft Archive for Redis

set greeting "hello world"
get greeting

#delete a key
del greeting

POC using C# Client

Source Code Location:

C# Client used: https://github.com/ServiceStack/ServiceStack.Redis

In the redis-cli.exe run command “monitor” to monitor all incoming calls

monitor

You Save a complex Class in memory with automatic serialization & deserialization using GetTypedClient()

We will save a Project class that has a GCF class as a parameter, which in turn has a List<> of Planes

   public class Project
    {
        public string ProjName { get; set; }
        public long Id { get; set; }
        public GCF gcfFile { get; set; }
    }
    public class GCF
    {
        public long Id { get; set; }
        public string Name { get; set; }
        public List<Plane> planes { get; set; }

        public GCF()
        {
            planes = new List<Plane>();
        }
    }
    public class Plane
    {
        public long Id { get; set; }
        public string Name { get; set; }
        public int x { get; set; }
        public int y { get; set; }
    }

To save this in memory

long lastId = 0;
using (IRedisClient client = new RedisClient())
{
    var projectClient = client.GetTypedClient<Project>();

    //new project
    var project = new Project() { ProjName = "Project1", Id = 1 }; ;

    //gcf file for the project
    var gcf = new GCF() { Name = "Gcf1", Id = 123};

    //planes in gcf
    gcf.planes.Add(new Plane() { Id = 1, Name = "plane1", x = 10, y = 11 });
    gcf.planes.Add(new Plane() { Id = 2, Name = "plane2", x = 15, y = 20 });

    project.gcfFile = gcf;

    var storedProject = projectClient.Store(project);
    lastId = storedProject.Id;
}

To Retrieve the saved Project class and de serialize it

using (IRedisClient client = new RedisClient())
{
    var projectClient = client.GetTypedClient<Project>();
    var project = projectClient.GetById(lastId);

    //get planes
    foreach (var plane in project.gcfFile.planes)
    {
        Console.WriteLine("Got plane {0}, with name {1}", plane.Id, 	plane.Name);
    }


}

Redis Datatypes

Strings

  1. Set
  2. Get
  3. Append
  4. INCR and DECR
  5. GETRANGE (works like substr) :getrange
  6. MGET : gets multiple keys set with MSET
  7. MSET: sets multiple keys/values: mset key 1 value 1 key 2 value2
  8. STRLEN
set user1 "{'name' : 'joe', 'email' : 'joe@gmail.com'}"
get user1

Lists

A sorted list of strings, sorted by insertion order

  1. LPUSH (prepend) and RPUSH (append): adds items to left side or right side of list.
  2. LREM: remove elements from list.
  3. LSET: set a value in list based on supplied index.
  4. LINDEX: return item by an index.
  5. LRANGE: get a range of elements from a list.
  6. LLEN: get the length of a list.
  7. LPOP and RPOP: remove and get the leftmost and rightmost items of a list. (to simulate a queue: lpop and then rpush)
  8. LTRIM: trim the list to a specified range. (ltrim 0 4)

List is efficient when you pull from front or end of a list (using it like a queue or a stack). There is no command to get all items of a list as that would be inefficient (it is a linked list: each item has a pointer to the previous item). You have to provide a range.

#add an item to a list
rpush gcf "{'gcf_id': '1','type':'plane', 'name':'plane1', x' : '10', 'y' : '20', 'z' : '15'}"
rpush gcf "{'gcf_id': '1','type':'plane','name':'plane2', x' : '11', 'y' : '21', 'z' : '15'}"
rpush gcf "{'gcf_id': '1','type':'plane','name':'plane3', x' : '12', 'y' : '22', 'z' : '17'}"

#get items
lrange gcf 0 10

#get item at an index not very efficient on large lists
lindex gcf 1

Sets

Collection of unique strings. Don’t have to check if an element already exists. Set will ignore item if it already exists.

#add
sadd geometrycolor "blue" "red" "white"
sadd materialcolor "black" "red" "purple"
#count
scard geometrycolor
#members
smembers geometrycolor
#difference between two sets -> white, blue
sdiff geometrycolor materialcolor
#intersection -> red
sinter geometrycolor materialcolor
#union
sunion geometrycolor materialcolor

Hashes

Maps between string fields and values. Redis is optimized for Hashes & hashes are an efficient way to store data in Redis.


#on hash  called h_gcf, set id = 1
hset ht_gcf id "1"
hset ht_gcf plane1 "{'type':'plane', x' : '10', 'y' : '20', 'z' : '15'}"
hset ht_gcf plane2 "{'type':'plane', x' : '12', 'y' : '22', 'z' : '16'}"

#get
hget ht_gcf id
hget ht_gcf plane1

#get multiple 
hmget  ht_gcf id plane1 plane2

# can all use hgetall to get all
hgetall ht_gcf

#get all keys
hkeys ht_gcf

Sorted Sets

Pub And Sub

Channel 1 : open cli in window 1. Subscribes to a channel called greeting

#subscribe to greetings channel
subscribe greetings

#subscribe to all channels starting with greet
psubscribe greet*

#unsubscribe
unsubscribe greetings
punsubscribe greet*

Channel 2: open cli in window 2: publishes to a channel called greeting

publish greetings "hello"

Transactions

multi : starts a transaction

—-do some work

exec: executes the transaction

Simple property setting (using IRedisNativeClient)

using (IRedisNativeClient client = new RedisClient())
{
    client.Set("urn:messages:1", Encoding.UTF8.GetBytes("Hello C# World!"));
}

using (IRedisNativeClient client = new RedisClient())
{
    var result = Encoding.UTF8.GetString(client.Get("urn:messages:1"));
    Console.WriteLine("Message: {0}", result);
}

Get and set a List using (IRedisClient, which is a higher level of abstraction)

using (IRedisClient client = new RedisClient())
{
    var customerNames = client.Lists["urn:customernames"];
    customerNames.Clear();
    customerNames.Add("Joe");
    customerNames.Add("Mary");
    customerNames.Add("Bob");
}

using (IRedisClient  = new RedisClient())
{
    var customerNames = client.Lists["urn:customernames"];
    foreach (var customerName in customerNames)
    {
        Console.WriteLine("Customer: {0}", customerName);
    }
}

Redis on Azure