I want to get all the sets from Redis using a list of keys in single call. As per the documentation, Redis provides SSCAN command for that but as I am using StackExchange.Redis as a Redis adapter, I guess this command does not have any such method in this adapter. So there two things I am looking for:
- I looking forward to execute SSCAN using the LUA script but was not able to find any such example over the internet. Can anyone share how to call SSCAN from LUA with multiple SET Keys.
- Also for the StackExchange.Redis, if I execute multiple SetMembers() in a transaction, is it similar to use SSCAN() command using LUA script?
Thanks
get multiple sets in a single call by passing list of Set keys
I'm unclear about the specific requirements here, so there are probably several ways to do that. The simplest is by calling SUNION
, which will dedupe and return the results w/o order.
Another option is to use a Lua script, such as:
local reply = {}
for i = 1,#KEYS do
local elems = redis.call('SMEMBERS', KEYS[i])
table.insert(reply, elems)
end
return reply
redis-cli example (sorry, .NET isn't my forte):
$ redis-cli SADD s1 foo bar
(integer) 2
$ redis-cli SADD s2 baz qaz
(integer) 2
$ redis-cli --eval script.lua s1 s2
1) 1) "foo"
2) "bar"
2) 1) "baz"
2) "qaz"
Note: if your Sets have a lot of members then getting all of them, regardless the approach, is going to be "expensive" - reconsider the need for that.
The sample C# code to get many SETs in a single call is as following:
I am using StackExchange.Redis as a Redis connector:
using StackExchange.Redis;
using System;
using System.Text;
namespace RedisGetMultipleKeys
{
/// <summary>
/// Class to perofrme operations on SE.Redis
/// </summary>
class Program
{
/// <summary>
/// Executes necessary pre-requisites
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
//Connect Redis
var _cache = Program.Connect();
//Store 10k Sets
string prefix = "user";
StringBuilder keys = new StringBuilder();
for (int i = 0; i < 10000; i++)
{
keys.Append(" " + prefix + i);
_cache.SetAdd(prefix + i, i);
}
var keyList = new RedisKey[10000];
//Generate keys array
for (int i = 0; i < 10000; i++)
{
var key = new RedisKey();
key = prefix + i;
keyList.SetValue(key, i);
}
var startTime = DateTime.Now;
//Perform SUNION
var values = _cache.SetCombine(SetOperation.Union, keyList);
var endTime = DateTime.Now;
TimeSpan diff = endTime.Subtract(startTime);
Console.WriteLine("total time taken to read 10k keys = " + diff);
Console.Read();
//TODO: to be changed accordingly to read Set values returned other than String
foreach (var value in values)
{
Console.WriteLine(value.ToString());
}
endTime = DateTime.Now;
diff = endTime.Subtract(startTime);
Console.WriteLine("total time taken to read 10k keys = " + diff);
Console.Read();
}
/// <summary>
/// Connects to Redis db
/// </summary>
/// <returns>Returns an instance of Redis db</returns>
private static IDatabase Connect()
{
string redisConnection = "localhost:6379,ssl=false,allowAdmin=true,ConnectRetry=3,ConnectTimeout=5000,defaultDatabase=1";
ConnectionMultiplexer connection = ConnectionMultiplexer.Connect(redisConnection);
return connection.GetDatabase();
}
}
}
I hope it will help the C# developers looking for the solution. Thanks to Mgravell from SE.Redis dev team for helping me by his suggestions. More discussion could be found here at GitHub How to get multiple sets by passing set key list in a single call