IRedisClient
Interfejsy API do obsługi LUA po stronie serwera redis zostały przeniesione do bardziej przyjaznych dla użytkownika interfejsów API poniżej:
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);
}
Wydajne SKANOWANIE w LUA #
Poniższy interfejs API C# zwraca pierwszych 10 wyników pasujących do key:*
wzór:
var keys = Redis.ScanAllKeys(pattern: "key:*", pageSize: 10)
.Take(10).ToList();
Jednak powyższy interfejs API przesyłania strumieniowego C# wymaga nieznanej liczby operacji Redis (powiązanych z liczbą kluczy w Redis), aby zakończyć żądanie. Liczbę wywołań SCAN można zmniejszyć, wybierając wyższy pageSize
aby powiedzieć Redisowi, aby skanował więcej kluczy za każdym razem, gdy wywoływana jest operacja SCAN.
Ponieważ liczba wywołań API może potencjalnie skutkować dużą liczbą operacji Redis, może to spowodować niedopuszczalne opóźnienie z powodu opóźnienia wielu zależnych wywołań sieci zdalnej. Prostym rozwiązaniem jest zamiast tego wykonywanie wielu wywołań SCAN w toku na serwerze Redis, eliminując opóźnienia sieciowe wielu wywołań SCAN, np.:
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
ExecLua
API zwraca tę złożoną odpowiedź tabeli LUA w Children
zbiór RedisText
Odpowiedź.
Alternatywna złożona odpowiedź API nr
Innym sposobem na zwrócenie złożonych struktur danych w operacji LUA jest serializacja wyniku jako JSON
return cjson.encode(results)
Do którego możesz uzyskać dostęp jako surowy JSON, analizując odpowiedź jako ciąg znaków za pomocą:
string json = redis.ExecLuaAsString(FastScanScript, "key:*", "10");
INFORMACJE
Jest to również podejście stosowane w RedisServices Redis React.
ExecCachedLua #
ExecCachedLua to wygodny interfejs API wysokiego poziomu, który eliminuje księgowość wymaganą do wykonywania wysokowydajnych skryptów LUA serwera, na które cierpi wiele problemów związanych z procedurami składowanymi RDBMS, które zależą od istniejącego stanu w RDBMS, który należy zaktualizować za pomocą najnowsza wersja procedury składowanej.
Dzięki Redis LUA możesz albo wysłać, przeanalizować, załadować, a następnie wykonać cały skrypt LUA za każdym razem, gdy jest on wywoływany, lub alternatywnie możesz wstępnie załadować skrypt LUA do Redis raz podczas uruchamiania, a następnie wykonać go za pomocą skrótu SHA1 skryptu. Problem polega na tym, że jeśli serwer Redis zostanie przypadkowo opróżniony, pozostaniesz z uszkodzoną aplikacją polegającą na istniejącym wcześniej skrypcie, którego już nie ma. Nowy ExecCachedLua
API zapewnia to, co najlepsze z obu światów, w których zawsze wykona skompilowany skrypt SHA1, oszczędzając przepustowość i procesor, ale także odtworzy skrypt LUA, jeśli już nie istnieje.
Zamiast tego możesz wykonać powyższy skompilowany skrypt LUA według jego identyfikatora SHA1, który nadal działa niezależnie od tego, czy nigdy nie istniał, czy został usunięty w czasie wykonywania, np.:
// #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"));
Przykłady użycia #
Oto jak zaimplementować ZPOP w Lua, aby usunąć przedmioty o najniższej randze z posortowanego zestawu:
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]
I jak wdrożyć ZREVPOP aby usunąć przedmioty o najwyższej randze z posortowanego zestawu:
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]
Inne przykłady #
Zwracanie int
:
int intVal = Redis.ExecLuaAsInt("return 123"); //123
int intVal = Redis.ExecLuaAsInt("return ARGV[1] + ARGV[2]", "10", "20"); //30
Zwracanie string
:
//Hello, Redis Lua!
var strVal = Redis.ExecLuaAsString(@"return 'Hello, ' .. ARGV[1] .. '!'", "Redis Lua");
Zwracanie List
ciągów:
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, ...]
Więcej przykładów można znaleźć w testach Redis Eval Lua