Redis
 sql >> Baza danych >  >> NoSQL >> Redis

Interfejsy API RedisClient LUA

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


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Znajdowanie kluczy za pomocą symboli wieloznacznych

  2. Pytania dotyczące Redis, Node.js i Socket.io

  3. Połącz się z AWS ElastiCache z szyfrowaniem podczas transportu + uwierzytelnianiem z klienta innego niż redis-cli+stunnel

  4. Redis - tabele Lua jako wartości zwracane - dlaczego to nie działa?

  5. System nie został uruchomiony z systemem systemd jako systemem init (PID 1). Nie mogę działać