Ersel Bozkartal
Ersel Bozkartal

Reputation: 73

Redis Lua Script Return Table and parse object

I have a problem,

local searchkey=@searchkey
local blockKeys = redis.call('keys', searchkey)
local table = {}
for i = 0, #blockKeys, 1 do
    local seats = redis.call('HVALS', blockKeys[i])
    table[i] = seats
end
return table

I want parse this table data for .net obj I used StackExchange.Redis library and lua return RedisResult but lua table data isn't parse RedisValue[]

Does anyone have an idea?

Upvotes: 1

Views: 2022

Answers (2)

Marc Gravell
Marc Gravell

Reputation: 1062780

A RedisResult is a general purpose wrapper for data of an unknown shape. There are operators that allow you to interpret the data in a range of ways, for example:

RedisResult val = ...

// simple
int asInt = (int)val; // a single integer
string asString = (string)val; // a single string

string[] asStrings = (string[])val; // a table of strings
double[] asDoubles = (double[])val; // a table of doubles

// more structured

var asKeys = (RedisKey[])val; // a table of keys
var asValues = (RedisValue[])val; // a table of values
var asMulti = (RedisResult[])val; // a table of general purpose values

So you can probably just cast it to what you need. However: using KEYS in the script is a big problem and you should really change that.


To address the question from comments:

Why I dont use keys , can you explain it to me ? Because I check performance, and keys is better than scan, and for table, hvals return binary object so => key, { {key, obj}, {key, obj}}

To quote from the redis documentation:

Warning: consider KEYS as a command that should only be used in production environments with extreme care. It may ruin performance when it is executed against large databases. This command is intended for debugging and special operations, such as changing your keyspace layout. Don't use KEYS in your regular application code.

Each redis instance has a single-threaded core for serving requests. KEYS looks fine on small databases, but with or without a filter the performance is O(N) where N is the total number of keys in the database, and for large systems: it can be catastrophically bad - meaning: taking 10s of seconds to return. Usually, redis operations are expected to take milliseconds at worst, and while your KEYS operation runs: nothing else can. It totally blocks the server for that period.

You note that KEYS is more efficient than SCAN, and in some ways that is true. The entire point of SCAN is that it allows you to do the operation as a (potentially very long) series of small batches - "scan the first 100; now scan the next 100 from there; and the next 100". This has a lot more overhead and latency, and involves more round-trips to the server, but the advantage is that it doesn't block the server core for a single huge chunk of time.

However! Usually, a better approach to either of these is to use a set of the things that you expect to match your data. Let's say that you have a big database and you're interested in all the /foo/{whatever} data. Now; rather than using KEYS or SCAN to find those values, if you need to iterate all the keys in that family, it is viable to simply drop all the keys into a set. So when you create /foo/abc you also drop /foo/abc into the set /foo/_keys (or whatever; there is no convention here) via sadd. Now: to iterate all the keys in that family, you just iterate the set /foo/_keys - which is a much more appropriate API.

Upvotes: 2

Ersel Bozkartal
Ersel Bozkartal

Reputation: 73

var asMulti = (RedisResult[])val;
foreach (var item in asMulti)
{
     var asd = (RedisValue[])item;
}

my script return table and I think this is RedisResult[] and inside obj so design

"key, { {key, obj}, {key, obj}}"

Upvotes: 2

Related Questions