X

Redis for .NET Developer – Lua Scripting

Redis

Redis Lua Scripting

Redis provides a way to extend its functionality on the server side by providing support for Lua Scripting. If you are coming from a relational database world, you already know that you can use Stored Procedures to extend functionality of your relational database. Now, you may also know that some people do frown upon using stored procedures, I think one could also think of using scripting in Redis sort of belongs in the same category. Nevertheless its still good to know what you can do with Redis and Lua.

If you want to learn more Lua try this site http://tylerneylon.com/a/learn-lua/

In order to call Lua Script from Redis.StackExchange library one can use the LuaScript class or IServer.ScriptLoad(Async), IServer.ScriptExists(Async), IServer.ScriptFlush(Async), IDatabase.ScriptEvaluate, and IDatabaseAsync.ScriptEvaluateAsync methods.

Lets try to do something with the redis console first by using the redis-cli

$redis-cli

127.0.0.1:6379> SCRIPT LOAD "return 'hello redis'"
"69dd69fc0ba1e25d8e2972008b6baee8eccf7da6"

127.0.0.1:6379> evalsha 69dd69fc0ba1e25d8e2972008b6baee8eccf7da6 0
"hello redis"

As you can see we first load the script and we get back a SHA1 Hash from it. Redis basically stores the information in one of its mapping table and we can reuse the sha1 hash to call the script by using the EVALSHA command, which in this case gave us back “hello redis”

Remember: When Redis is running your Lua script, it will not run anything else because Redis is single threaded

C# code using Redis Lua Script

 class Program
    {
        static void Main(string[] args)
        {

            const string script = @"
local function MGETSUM(keys)
    local sum = 0
    for _,key in ipairs(keys) do
        local val = redis.call('GET', key) or 0
        sum = sum + tonumber(val)
    end
    return sum
end
return MGETSUM(KEYS)";

            var redis = RedisStore.RedisCache;            

            var server = RedisStore.Server;

            var test1 = "test1";
            var test2 = "test2";
            var test3 = "test3";

            //delete the keys
            redis.KeyDelete(test1, CommandFlags.FireAndForget);
            redis.KeyDelete(test2, CommandFlags.FireAndForget);
            redis.KeyDelete(test3, CommandFlags.FireAndForget);

            redis.StringSet(test1, 1);
            redis.StringSet(test2, 2);
            redis.StringSet(test3, 3);

            RedisKey[] keys = { test1, test2, test3 };

            byte[] hash = server.ScriptLoad(script);

            //get back the sha1 key
            string hexHash = string.Concat(hash.Select(x => x.ToString("X2")));

            var result = redis.ScriptEvaluate(hexHash, keys);
          
            Console.WriteLine(result); //result will be 6 

            Console.ReadKey();
        }

You may realize that every time we call the server we need to load the script and then execute on it, there is also another way that StackExchange Redis allows us to to avoid the overhead of transmitting the script text for every call. One can convert a LuaScript into a LoadedLuaScript like the code below:

  //create another script to store 
            var script2 = @"
local name=@name
local age=@age
return name..' '..age
";
            
            var prepared = LuaScript.Prepare(script2);
            //we now need to cache this loaded script somewhere
            var loaded = prepared.Load(server);

            //such that we do not need to uplaod the script every time
            var val = loaded.Evaluate(redis, new { name="taswar", age=5});

            //Output: taswar 5
            Console.WriteLine(val);

            val = loaded.Evaluate(redis, new { name = "peter", age = 25 });

            //Output: peter 25
            Console.WriteLine(val);

You would cache the loaded value somewhere in your application, usually its best to load the scripts when you start your application

So this covers the basic usage of Redis LuaScript, in the next blog post I will cover how to use Geo spatial data in Redis.

For the code please visit
https://github.com/taswar/RedisForNetDevelopers/tree/master/12.RedisLua/RedisLua

For previous Redis topics

  1. Intro to Redis for .NET Developers
  2. Redis for .NET Developer – Connecting with C#
  3. Redis for .NET Developer – String Datatype
  4. Redis for .NET Developer – String Datatype part 2
  5. Redis for .NET Developer – Hash Datatype
  6. Redis for .NET Developer – List Datatype
  7. Redis for .NET Developer – Redis Sets Datatype
  8. Redis for .NET Developer – Redis Sorted Sets Datatype
  9. Redis for .NET Developer – Redis Hyperloglog
  10. Redis for .NET Developer – Redis Pub Sub
  11. Redis for .NET Developers – Redis Pipeline Batching
  12. Redis for .NET Developers – Redis Transactions
Categories: .NET Redis
Taswar Bhatti:
Related Post