O
IRedisClient
As APIs para suporte a LUA do lado do servidor redis foram reformuladas nas APIs mais fáceis de usar abaixo:public interface IRedisClient
{
//Eval/Lua operations
T ExecCachedLua<T>(string scriptBody, Func<string, T> scriptSha1);
RedisText ExecLua(string body, params string[] args);
RedisText ExecLua(string luaBody, string[] keys, string[] args);
RedisText ExecLuaSha(string sha1, params string[] args);
RedisText ExecLuaSha(string sha1, string[] keys, string[] args);
string ExecLuaAsString(string luaBody, params string[] args);
string ExecLuaAsString(string luaBody, string[] keys, string[] args);
string ExecLuaShaAsString(string sha1, params string[] args);
string ExecLuaShaAsString(string sha1, string[] keys, string[] args);
int ExecLuaAsInt(string luaBody, params string[] args);
int ExecLuaAsInt(string luaBody, string[] keys, string[] args);
int ExecLuaShaAsInt(string sha1, params string[] args);
int ExecLuaShaAsInt(string sha1, string[] keys, string[] args);
List<string> ExecLuaAsList(string luaBody, params string[] args);
List<string> ExecLuaAsList(string luaBody, string[] keys, string[] args);
List<string> ExecLuaShaAsList(string sha1, params string[] args);
List<string> ExecLuaShaAsList(string sha1, string[] keys, string[] args);
string CalculateSha1(string luaBody);
bool HasLuaScript(string sha1Ref);
Dictionary<string, bool> WhichLuaScriptsExists(params string[] sha1Refs);
void RemoveAllLuaScripts();
void KillRunningLuaScript();
string LoadLuaScript(string body);
}
Digitalização eficiente em LUA #
A API C# abaixo retorna os 10 primeiros resultados correspondentes à
key:*
padronizar:var keys = Redis.ScanAllKeys(pattern: "key:*", pageSize: 10)
.Take(10).ToList();
No entanto, a API de streaming C# acima requer um número desconhecido de operações do Redis (limitado ao número de chaves no Redis) para concluir a solicitação. O número de chamadas SCAN pode ser reduzido escolhendo um
pageSize
maior para dizer ao Redis para escanear mais chaves cada vez que a operação SCAN for chamada. Como o número de chamadas de API tem o potencial de resultar em um grande número de operações Redis, pode acabar gerando um atraso inaceitável devido à latência de várias chamadas de rede remota dependentes. Uma solução fácil é realizar as várias chamadas SCAN em processo no Redis Server, eliminando a latência de rede de várias chamadas SCAN, por exemplo:
const string FastScanScript = @"
local limit = tonumber(ARGV[2])
local pattern = ARGV[1]
local cursor = 0
local len = 0
local results = {}
repeat
local r = redis.call('scan', cursor, 'MATCH', pattern, 'COUNT', limit)
cursor = tonumber(r[1])
for k,v in ipairs(r[2]) do
table.insert(results, v)
len = len + 1
if len == limit then break end
end
until cursor == 0 or len == limit
return results";
RedisText r = redis.ExecLua(FastScanScript, "key:*", "10");
r.Children.Count.Print() //= 10
O
ExecLua
A API retorna essa resposta complexa da tabela LUA no Children
coleção do RedisText
Resposta. Resposta de API complexa alternativa #
Outra maneira de retornar estruturas de dados complexas em uma operação LUA é serializar o resultado como JSON
return cjson.encode(results)
Que você pode acessar como JSON bruto analisando a resposta como uma String com:
string json = redis.ExecLuaAsString(FastScanScript, "key:*", "10");
INFORMAÇÕES
Essa também é a abordagem usada nos RedisServices do Redis React.
ExecCachedLua #
ExecCachedLua é uma API de alto nível conveniente que elimina a escrituração necessária para executar scripts LUA de servidor de alto desempenho que sofrem de muitos dos problemas que os procedimentos armazenados do RDBMS têm que dependem do estado pré-existente no RDBMS que precisa ser atualizado com o última versão do procedimento armazenado.
Com o Redis LUA, você tem a opção de enviar, analisar, carregar e executar todo o script LUA toda vez que for chamado ou, alternativamente, pode pré-carregar o script LUA no Redis uma vez na inicialização e executá-lo usando o hash SHA1 do script. O problema com isso é que, se o servidor Redis for liberado acidentalmente, você ficará com um aplicativo quebrado contando com um script pré-existente que não está mais lá. O novo
ExecCachedLua
A API fornece o melhor dos dois mundos, onde sempre executará o script SHA1 compilado, economizando largura de banda e CPU, mas também recriará o script LUA se ele não existir mais. Em vez disso, você pode executar o script LUA compilado acima por seu identificador SHA1, que continua a funcionar independentemente de nunca ter existido ou ter sido removido em tempo de execução, por exemplo:
// #1: Loads LUA script and caches SHA1 hash in Redis Client
r = redis.ExecCachedLua(FastScanScript, sha1 =>
redis.ExecLuaSha(sha1, "key:*", "10"));
// #2: Executes using cached SHA1 hash
r = redis.ExecCachedLua(FastScanScript, sha1 =>
redis.ExecLuaSha(sha1, "key:*", "10"));
// Deletes all existing compiled LUA scripts
redis.ScriptFlush();
// #3: Executes using cached SHA1 hash, gets NOSCRIPT Error,
// re-creates then re-executes the LUA script using its SHA1 hash
r = redis.ExecCachedLua(FastScanScript, sha1 =>
redis.ExecLuaSha(sha1, "key:*", "10"));
Exemplos de uso #
Veja como você pode implementar um ZPOP em Lua para remover os itens com a classificação mais baixa de um conjunto ordenado:
var luaBody = @"
local val = redis.call('zrange', KEYS[1], 0, ARGV[1]-1)
if val then redis.call('zremrangebyrank', KEYS[1], 0, ARGV[1]-1) end
return val";
var i = 0;
var alphabet = 26.Times(c => ((char)('A' + c)).ToString());
alphabet.ForEach(x => Redis.AddItemToSortedSet("zalphabet", x, i++));
//Remove the letters with the lowest rank from the sorted set 'zalphabet'
var letters = Redis.ExecLuaAsList(luaBody, keys: new[] { "zalphabet" }, args: new[] { "3" });
letters.PrintDump(); //[A, B, C]
E como implementar ZREVPOP para remover itens com a classificação mais alta de um conjunto classificado:
var luaBody = @"
local val = redis.call('zrange', KEYS[1], -ARGV[1], -1)
if val then redis.call('zremrangebyrank', KEYS[1], -ARGV[1], -1) end
return val";
var i = 0;
var alphabet = 26.Times(c => ((char)('A' + c)).ToString());
alphabet.ForEach(x => Redis.AddItemToSortedSet("zalphabet", x, i++));
//Remove the letters with the highest rank from the sorted set 'zalphabet'
List<string> letters = Redis.ExecLuaAsList(luaBody,
keys: new[] { "zalphabet" }, args: new[] { "3" });
letters.PrintDump(); //[X, Y, Z]
Outros exemplos #
Retornando um
int
:int intVal = Redis.ExecLuaAsInt("return 123"); //123
int intVal = Redis.ExecLuaAsInt("return ARGV[1] + ARGV[2]", "10", "20"); //30
Retornando uma
string
://Hello, Redis Lua!
var strVal = Redis.ExecLuaAsString(@"return 'Hello, ' .. ARGV[1] .. '!'", "Redis Lua");
Retornando uma
List
de cordas:Enum.GetNames(typeof(DayOfWeek)).ToList()
.ForEach(x => Redis.AddItemToList("DaysOfWeek", x));
var daysOfWeek = Redis.ExecLuaAsList("return redis.call('LRANGE', 'DaysOfWeek', 0, -1)");
daysOfWeek.PrintDump(); //[Sunday, Monday, Tuesday, ...]
Mais exemplos podem ser encontrados nos testes Redis Eval Lua