1. redis uses lua script syntax
Redis Eval command - execute Lua script
redis 127.0.0.1:6379> eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second 1) "key1" 2) "key2" 3) "first" 4) "second"
among
Script: the parameter is a Lua 5.1 script program. A script need not (and should not) be defined as a Lua function.
numkeys: used to specify the number of key name parameters.
key [key...]: calculated from the third parameter of EVAL, it indicates the Redis KEYS (KEYS) used in the script. These key name parameters can be accessed in Lua through the global variable KEYS array with 1 as the base address (KEYS[1], KEYS[2], and so on).
arg [arg...]: additional parameters are accessed through the global variable ARGV array in Lua, and the access form is similar to the KEYS variable (ARGV[1], ARGV[2], and so on).
You can directly execute the written lua script through redis cli -- Eval:
redis-cli --eval /test.lua 0
2,Lua
lua is a lightweight and compact script language, which is written in standard C language and open in the form of source code. Its design purpose is to be embedded in the application, so as to provide flexible expansion and customization functions for the application.
print('hello world') -- notes a=1 b="abc" c={} d=print c={"a","b","c"} print(type(a)) print(type(b)) print(type(c)) print(type(d)) -- multiline comment [[ -------- Output ------ number string table function ]] a="single 'quoted' string and double \"quoted\" string inside" b='single \'quoted\' string and double "quoted" string inside' c= [[ multiple line with 'single' and "double" quoted strings inside.]] print(a) print(b) print(c) [[ -------- Output ------ single 'quoted' string and double "quoted" string inside single 'quoted' string and double "quoted" string inside multiple line with 'single' and "double" quoted strings inside. ]] a,b,c,d,e = 1, 2, "three", "four", 5 a,b,c,d,e = 1, 1.123, 1E9, -123, .0008 print("a="..a, "b="..b, "c="..c, "d="..d, "e="..e) [[ -------- Output ------ a=1 b=1.123 c=1000000000 d=-123 e=0.0008 ]] address={} -- empty address address.Street="Wyman Street" address.StreetNumber=360 address.AptNumber="2a" address.City="Watertown" address.State="Vermont" address.Country="USA" print(address.StreetNumber, address["AptNumber"]) -- end end a=1 if a==1 then print ("a is one") end c=3 if c==1 then print("c is 1") elseif c==2 then print("c is 2") else print("c isn't 1 or 2, c is "..tostring(c)) end a=1 b=(a==1) and "one" or "not one" print(b) -- b = ((a==1) ? "one" : "not one") -- loop a=1 while a~=5 do -- Lua uses ~= to mean not equal a=a+1 io.write(a.." ") end a=0 repeat a=a+1 print(a) until a==5 for a=1,6,3 do io.write(a) end -- 14 [[ for (int i = 1; i < 6; i += 3) { printf(i); } ]] for key,value in pairs({1,2,3,4}) do print(key, value) end [[ -------- Output ------ 1 1 2 2 3 3 4 4 ]] a={1,2,3,4,"five","elephant", "mouse"} for i,v in pairs(a) do print(i,v) end [[ -------- Output ------ 1 1 2 2 3 3 4 4 5 five 6 elephant 7 mouse ]] -- break a=0 while true do a=a+1 if a==10 then break end end -- function function myFirstLuaFunctionWithMultipleReturnValues(a,b,c) return a,b,c,"My first lua function with multiple return values", 1, true end a,b,c,d,e,f = myFirstLuaFunctionWithMultipleReturnValues(1,2,"three") print(a,b,c,d,e,f) [[ -------- Output ------ 1 2 three My first lua function with multiple return values 1 true ]] -- local local variable function myfunc() local b=" local variable" a="global variable" print(a,b) end function printf(fmt, ...) io.write(string.format(fmt, ...)) end printf("Hello %s from %s on %s\n", os.getenv"USER" or "there", _VERSION, os.date()) -- Math functions: -- math.abs, math.acos, math.asin, math.atan, math.atan2, -- math.ceil, math.cos, math.cosh, math.deg, math.exp, math.floor, -- math.fmod, math.frexp, math.huge, math.ldexp, math.log, math.log10, -- math.max, math.min, math.modf, math.pi, math.pow, math.rad, -- math.random, math.randomseed, math.sin, math.sinh, math.sqrt, -- math.tan, math.tanh -- String functions: -- string.byte, string.char, string.dump, string.find, string.format, -- string.gfind, string.gsub, string.len, string.lower, string.match, -- string.rep, string.reverse, string.sub, string.upper -- Table functions: -- table.concat, table.insert, table.maxn, table.remove, table.sort -- IO functions: -- io.close , io.flush, io.input, io.lines, io.open, io.output, io.popen, -- io.read, io.stderr, io.stdin, io.stdout, io.tmpfile, io.type, io.write, -- file:close, file:flush, file:lines ,file:read, -- file:seek, file:setvbuf, file:write print(io.open("file doesn't exist", "r")) -- OS functions: -- os.clock, os.date, os.difftime, os.execute, os.exit, os.getenv, -- os.remove, os.rename, os.setlocale, os.time, os.tmpname -- require Import package require( "iuplua" ) ml = iup.multiline { expand="YES", value="Quit this multiline edit app to continue Tutorial!", border="YES" } dlg = iup.dialog{ml; title="IupMultiline", size="QUARTERxQUARTER",} dlg:show() print("Exit GUI app to continue!") iup.MainLoop()
Lua runs a garbage collector to collect all dead objects (that is, objects that can no longer be accessed in Lua) to complete automatic memory management. All memory used in Lua, such as string, table, user data, function, thread, internal structure, etc., are subject to automatic management.
Lua implements an incremental tag scan collector. It uses these two numbers to control the garbage collection cycle: the garbage collector intermittent rate and the garbage collector step rate. Both numbers are in percentages (for example, a value of 100 internally represents 1).
3. redis uses Lua
Return the result through return and redis Call to execute the redis command:
eval "return redis.call('keys','*')" 0
The above command returns all keys, which is similar to executing keys directly*
The following command deletes all key values in dict * format
eval "local redisKeys = redis.call('keys',KEYS[1]..'*');for i,k in pairs(redisKeys) do redis.call('del',k);end;return redisKeys;" 1 dict
Expand as follows
local redisKeys = redis.call('keys',KEYS[1]..'*'); for i,k in pairs(redisKeys) do redis.call('del',k); end; return redisKeys;
The following command deletes all key values
eval "local sum = 0;for i,k in pairs(redis.call('keys','*')) do redis.call('del', k);sum=sum+1;end; return 'clear '..sum..' key'" 0
like this:
Batch production key value, set expiration time, parameters: 2. Number of keys, key prefix, value of key, expiration time of key (optional)
eval "for i=1,KEYS[1],1 do local k=KEYS[2]..i; redis.call('set',k,ARGV[1]);if ARGV[2] then redis.call('expire',k,ARGV[2]) end;end;return redis.call('keys',KEYS[2]..'*');" 2 10 test 0 20
Delete all key s with value 0. Parameters: 0, value X
eval "local ks = {};for i,k in pairs(redis.call('keys','*')) do local v = redis.call('get',k);if v==ARGV[1] then redis.call('del',k);table.insert(ks,k); end;end;return ks;" 0 0
Delete all key s that never expire
eval "local ks = {};for i,k in pairs(redis.call('keys','*')) do local ttl = redis.call('ttl',k);if ttl==-1 then redis.call('del',k);table.insert(ks,k); end;end;return ks;" 0
Get the list of all key s with 0 value and test prefix. Parameters: 2, x, y
eval "local ks = {};for i,k in pairs(redis.call('keys',KEYS[1]..'*')) do local v = redis.call('get',k);if v==ARGV[1] then table.insert(ks,k); end;end;return ks;" 1 test 0
redis distributed lock is implemented and locked. If there is no lock, set local to 233, and set the expiration time to 60. If 1 is returned, the lock is successful, and 0 is returned, the lock fails. This operation is an atomic operation and can be replaced by the equivalent command set lock 233 nx px 60:
eval "if redis.call('get',KEYS[1]) then return 0;else redis.call('set',KEYS[1],ARGV[1]);redis.call('expire',KEYS[1],ARGV[2]);return 1;end;" 1 lock 233 60
Expand as follows
if redis.call('get',KEYS[1]) then return 0; else redis.call('set',KEYS[1],ARGV[1]); redis.call('expire',KEYS[1],ARGV[2]); return 1; end
redis distributed lock implementation, which releases the lock. If there is no lock, it does not need to be released. If there is a lock and the value is consistent with the passed in value, the lock is deleted and the release is successful. In other cases, the release fails. Success: 1, failure: 0.
eval "local v = redis.call('get',KEYS[1]);if v then if v~=ARGV[1] then return 0;end;redis.call('del',KEYS[1]);end;return 1;" 1 lock 233
Expand as follows
local v = redis.call('get',KEYS[1]); if v then -- If it is different from the value passed in, a return of 0 indicates failure if v~=ARGV[1] then return 0; end; -- delete key redis.call('del',KEYS[1]); end; return 1;
1. A program lock_a. Set value 233, lock for 600 seconds, return 0 success
2. B program tries to give lock_a locks, returns 0 and fails
3. B program attempts to release A's lock (which is of course not allowed), and B does not know lock_ The value of A, failed to release the lock, and returned 0
4. A program releases the lock, returns 1, and the release is successful
5. B program tries to give lock again_ A lock up, lock up successfully
4. redisTemplate method encapsulation for executing script
@Component public class RedisUtil { @Resource private RedisTemplate<String, Object> redisTemplate; /** * Execute lua script * @author hengyumo * @since 2021-06-05 * * @param luaScript lua script * @param returnType Returned structure type * @param keys KEYS * @param argv ARGV * @param <T> generic paradigm * * @return Results of execution */ public <T> T executeLuaScript(String luaScript, Class<T> returnType, String[] keys, String... argv) { return redisTemplate.execute(RedisScript.of(luaScript, returnType), new StringRedisSerializer(), new GenericToStringSerializer<>(returnType), Arrays.asList(keys), (Object[])argv); } }
It is easy to use. The following two scripts used above are used as examples:
@Resource private RedisUtil redisUtil; @Test @SuppressWarnings("unchecked") public void testExecuteLuaScript() { String script = "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}"; List<Object> list = (List<Object>)redisUtil.executeLuaScript(script, List.class, new String[] {"a", "b"}, "a", "b"); list.forEach(x -> System.out.println(x.toString())); script = "for i=1,KEYS[1],1 do local k=KEYS[2]..i; redis.call('set',k,ARGV[1]);" + "if ARGV[2] then redis.call('expire',k,ARGV[2]) end;end;" + "return redis.call('keys',KEYS[2]..'*');"; list = (List<Object>)redisUtil.executeLuaScript(script, List.class, new String[] {"10", "test"}, "0", "60"); list.forEach(x -> System.out.println(x.toString())); }
Output the result. The returned result is list < list >:
[a] [b] [a] [b] [test1] [test10] [test2] [test3] [test4] [test5] [test6] [test7] [test8] [test9]
View redis:
END
Writing is not easy, your little one 👍 Will make me more motivated.
Before the end, I'm willing to love again—— ink