IRedisClient
API untuk dukungan LUA sisi server redis telah difaktorkan ulang menjadi API yang lebih ramah pengguna di bawah ini:
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);
}
SCAN Efisien di LUA #
C# API di bawah ini mengembalikan 10 hasil pertama yang cocok dengan key:*
pola:
var keys = Redis.ScanAllKeys(pattern: "key:*", pageSize: 10)
.Take(10).ToList();
Namun C# Streaming API di atas memerlukan jumlah Operasi Redis yang tidak diketahui (terbatas pada jumlah kunci di Redis) untuk menyelesaikan permintaan. Jumlah panggilan SCAN dapat dikurangi dengan memilih pageSize
yang lebih tinggi untuk memberi tahu Redis agar memindai lebih banyak kunci setiap kali operasi SCAN dipanggil.
Karena jumlah panggilan API berpotensi menghasilkan Operasi Redis dalam jumlah besar, ini dapat menghasilkan penundaan yang tidak dapat diterima karena latensi beberapa panggilan jaringan jarak jauh yang bergantung. Solusi mudahnya adalah menjalankan beberapa panggilan SCAN dalam proses di Server Redis, menghilangkan latensi jaringan dari beberapa panggilan SCAN, mis:
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 mengembalikan respons tabel LUA yang kompleks ini di Children
kumpulan RedisText
Tanggapan.
Respons API Kompleks Alternatif #
Cara lain untuk mengembalikan struktur data yang kompleks dalam operasi LUA adalah dengan membuat serial hasil sebagai JSON
return cjson.encode(results)
Yang dapat Anda akses sebagai JSON mentah dengan menguraikan respons sebagai String dengan:
string json = redis.ExecLuaAsString(FastScanScript, "key:*", "10");
INFORMASI
Ini juga merupakan pendekatan yang digunakan dalam RedisServices Redis React.
ExecCachedLua #
ExecCachedLua adalah API tingkat tinggi yang nyaman yang menghilangkan pembukuan yang diperlukan untuk mengeksekusi Skrip LUA server berkinerja tinggi yang mengalami banyak masalah yang dimiliki prosedur tersimpan RDBMS yang bergantung pada keadaan yang sudah ada sebelumnya di RDBMS yang perlu diperbarui dengan versi terbaru dari Prosedur Tersimpan.
Dengan Redis LUA, Anda memiliki opsi untuk mengirim, mengurai, memuat, lalu mengeksekusi seluruh skrip LUA setiap kali dipanggil atau sebagai alternatif, Anda dapat memuat Skrip LUA ke Redis sekali di StartUp dan kemudian menjalankannya menggunakan hash SHA1 Skrip. Masalah dengan ini adalah bahwa jika server Redis secara tidak sengaja memerah, Anda dibiarkan dengan aplikasi yang rusak mengandalkan skrip yang sudah ada sebelumnya yang tidak ada lagi. ExecCachedLua
baru API memberikan yang terbaik dari kedua dunia di mana ia akan selalu mengeksekusi skrip SHA1 yang dikompilasi, menghemat bandwidth dan CPU tetapi juga akan membuat ulang Skrip LUA jika tidak ada lagi.
Sebagai gantinya, Anda dapat menjalankan skrip LUA yang dikompilasi di atas dengan pengenal SHA1-nya, yang terus bekerja terlepas dari apakah skrip itu tidak pernah ada atau dihapus saat runtime, mis:
// #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"));
Contoh Penggunaan #
Berikut cara menerapkan ZPOP di Lua untuk menghapus item dengan peringkat terendah dari set yang diurutkan:
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]
Dan bagaimana menerapkan ZREVPOP untuk menghapus item dengan peringkat tertinggi dari kumpulan yang diurutkan:
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]
Contoh lain #
Mengembalikan int
:
int intVal = Redis.ExecLuaAsInt("return 123"); //123
int intVal = Redis.ExecLuaAsInt("return ARGV[1] + ARGV[2]", "10", "20"); //30
Mengembalikan string
:
//Hello, Redis Lua!
var strVal = Redis.ExecLuaAsString(@"return 'Hello, ' .. ARGV[1] .. '!'", "Redis Lua");
Mengembalikan List
string:
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, ...]
Contoh lainnya dapat ditemukan di tes Redis Eval Lua