日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

Redis中的Lua 脚本

發(fā)布時間:2024/4/13 数据库 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Redis中的Lua 脚本 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Lua/?lu?/是一種輕量級腳本語言,它是用C 語言編寫的,跟數(shù)據(jù)的存儲過程有點類似。使用Lua 腳本來執(zhí)行Redis 命令的好處:

1、一次發(fā)送多個命令,減少網(wǎng)絡(luò)開銷。

2、Redis 會將整個腳本作為一個整體執(zhí)行,不會被其他請求打斷,保持原子性。

3、對于復(fù)雜的組合命令,我們可以放在文件中,可以實現(xiàn)程序之間的命令集復(fù)用。

?

在Redis 中調(diào)用Lua 腳本

使用eval /?'v?l/ 方法,語法格式:

redis> eval lua-script key-num [key1 key2 key3 ....] [value1 value2 value3 ....]

eval 代表執(zhí)行Lua 語言的命令。

lua-script 代表Lua 語言腳本內(nèi)容。

key-num 表示參數(shù)中有多少個key,需要注意的是Redis 中key 是從1 開始的,如果沒有key 的參數(shù),那么寫0。

[key1 key2 key3…]是key 作為參數(shù)傳遞給Lua 語言,也可以不填,但是需要和key-num 的個數(shù)對應(yīng)起來。

[value1 value2 value3 ….]這些參數(shù)傳遞給Lua 語言,它們是可填可不填的。

?

示例,返回一個字符串,0 個參數(shù):

redis> eval "return 'Hello World'" 0

在Lua 腳本中調(diào)用Redis 命令

使用redis.call(command, key [param1, param2…])進行操作。語法格式:

redis> eval "redis.call('set',KEYS[1],ARGV[1])" 1 lua-key lua-value

command 是命令,包括set、get、del 等。

key 是被操作的鍵。

param1,param2…代表給key 的參數(shù)。

注意跟Java 不一樣,定義只有形參,調(diào)用只有實參。

Lua 是在調(diào)用時用key 表示形參,argv 表示參數(shù)值(實參)

?

設(shè)置鍵值對

在Redis 中調(diào)用Lua 腳本執(zhí)行Redis 命令

redis> eval "return redis.call('set',KEYS[1],ARGV[1])" 1 leon 2673 redis> get leon

以上命令等價于set leon 2673。

在redis-cli 中直接寫Lua 腳本不夠方便,也不能實現(xiàn)編輯和復(fù)用,通常我們會把腳本放在文件里面,然后執(zhí)行這個文件。

在Redis 中調(diào)用Lua 腳本文件中的命令,操作Redis

創(chuàng)建Lua 腳本文件:

cd /usr/local/soft/redis5.0.5/src vim leon.lua

Lua 腳本內(nèi)容,先設(shè)置,再取值:

redis.call('set','leon','lua666') return redis.call('get','leon')

在Redis 客戶端中調(diào)用Lua 腳本

cd /usr/local/soft/redis5.0.5/src redis-cli --eval leon.lua 0

得到返回值:

[root@localhost src]# redis-cli --eval leon.lua 0 "lua666"

案例:對IP 進行限流

需求:在X 秒內(nèi)只能訪問Y 次。

設(shè)計思路:用key 記錄IP,用value 記錄訪問次數(shù)。

拿到IP 以后,對IP+1。如果是第一次訪問,對key 設(shè)置過期時間(參數(shù)1)。否則判斷次數(shù),超過限定的次數(shù)(參數(shù)2),返回0。如果沒有超過次數(shù)則返回1。超過時間,key 過期之后,可以再次訪問。

KEY[1]是IP, ARGV[1]是過期時間X,ARGV[2]是限制訪問的次數(shù)Y。

-- ip_limit.lua -- IP 限流,對某個IP 頻率進行限制,6 秒鐘訪問10 次 local num=redis.call('incr',KEYS[1]) if tonumber(num)==1 then redis.call('expire',KEYS[1],ARGV[1]) return 1 elseif tonumber(num)>tonumber(ARGV[2]) then return 0 else return 1 end

6 秒鐘內(nèi)限制訪問10 次,調(diào)用測試(連續(xù)調(diào)用10 次):

./redis-cli --eval "ip_limit.lua" app:ip:limit:192.168.8.111 , 6 10

app:ip:limit:192.168.8.111 是key 值,后面是參數(shù)值,中間要加上一個空格和一個逗號,再加上一個空格。

即:./redis-cli –eval [lua 腳本] [key…]空格,空格[args…]

多個參數(shù)之間用一個空格分割。

代碼:LuaTest.java

public class LuaTest {public static void main(String[] args) {Jedis jedis = getJedisUtil();jedis.eval("return redis.call('set',KEYS[1],ARGV[1])", 1,"test:lua:key","qingshan2673lua");System.out.println(jedis.get("test:lua:key"));for(int i=0; i<10; i++){limit();}}/*** 10秒內(nèi)限制訪問5次*/public static void limit(){Jedis jedis = getJedisUtil();// 只在第一次對key設(shè)置過期時間String lua = "local num = redis.call('incr', KEYS[1])\n" +"if tonumber(num) == 1 then\n" +"\tredis.call('expire', KEYS[1], ARGV[1])\n" +"\treturn 1\n" +"elseif tonumber(num) > tonumber(ARGV[2]) then\n" +"\treturn 0\n" +"else \n" +"\treturn 1\n" +"end\n";Object result = jedis.evalsha(jedis.scriptLoad(lua), Arrays.asList("localhost"), Arrays.asList("10", "5"));System.out.println(result);}private static Jedis getJedisUtil() {String ip = ResourceUtil.getKey("redis.host");int port = Integer.valueOf(ResourceUtil.getKey("redis.port"));String password = ResourceUtil.getKey("redis.password");JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();JedisPool pool = new JedisPool(jedisPoolConfig, ip, port, 10000, password);return pool.getResource();}}

?

總結(jié)

以上是生活随笔為你收集整理的Redis中的Lua 脚本的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。