本文介紹SpringBoot如果通過Lua腳本去執(zhí)行Redis,介紹簡單用法例子逗威,如對Lua腳本還不了解的可以先參考我這邊文章Lua腳本快速入門署穗,更深層次的用法請參考Redis官網(wǎng)
1. 添加依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2. 編寫Lua腳本
---
--- Created by Gjing.
--- DateTime: 2019/6/21 10:49
---
--- 獲取key
local key = KEYS[1]
--- 獲取value
local val = KEYS[2]
--- 獲取一個參數(shù)
local expire = ARGV[1]
--- 如果redis找不到這個key就去插入
if redis.call("get", key) == false then
--- 如果插入成功,就去設(shè)置過期值
if redis.call("set", key, val) then
--- 由于lua腳本接收到參數(shù)都會轉(zhuǎn)為String哈垢,所以要轉(zhuǎn)成數(shù)字類型才能比較
if tonumber(expire) > 0 then
--- 設(shè)置過期時間
redis.call("expire", key, expire)
end
return true
end
return false
else
return false
end
3. 編寫配置
/**
* @author Gjing
**/
@Configuration
public class LuaConfiguration {
@Bean
public DefaultRedisScript<Boolean> redisScript() {
DefaultRedisScript<Boolean> redisScript = new DefaultRedisScript<>();
redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("script/Test.lua")));
redisScript.setResultType(Boolean.class);
return redisScript;
}
}
4. 調(diào)用測試
/**
* @author Gjing
**/
@RestController
public class LockController {
@Resource
private DefaultRedisScript<Boolean> redisScript;
@Resource
private StringRedisTemplate stringRedisTemplate;
@GetMapping("/lua")
public ResponseEntity lua() {
List<String> keys = Arrays.asList("testLua", "hello lua");
Boolean execute = stringRedisTemplate.execute(redisScript, keys, "100");
assert execute != null;
return ResponseEntity.ok(execute);
}
}
5. 返回結(jié)果
-
執(zhí)行成功控制臺輸出
-
執(zhí)行失敗控制臺輸出
-
Redis中內(nèi)容
6. Redis使用Lua的好處
1.減少網(wǎng)絡(luò)開銷:本來5次網(wǎng)絡(luò)請求的操作,可以用一個請求完成扛拨,原先5次請求的邏輯放在redis服務(wù)器上完成耘分。使用腳本,減少了網(wǎng)絡(luò)往返時延绑警。
2.原子操作:Redis會將整個腳本作為一個整體執(zhí)行求泰,中間不會被其他命令插入。
3.復(fù)用:客戶端發(fā)送的腳本會永久存儲在Redis中计盒,意味著其他客戶端可以復(fù)用這一腳本而不需要使用代碼完成同樣的邏輯渴频。
7. Redis使用Lua的注意點
1.Lua腳本的bug特別可怕,由于Redis的單線程特點北启,一旦Lua腳本出現(xiàn)不會返回(不是返回值)得問題卜朗,那么這個腳本就會阻塞整個redis實例。
2.Lua腳本應(yīng)該盡量短小實現(xiàn)關(guān)鍵步驟即可咕村。(原因同上)
3.Lua腳本中不應(yīng)該出現(xiàn)常量Key场钉,這樣會導(dǎo)致每次執(zhí)行時都會在腳本字典中新建一個條目,應(yīng)該使用全局變量數(shù)組KEYS和ARGV, KEYS和ARGV的索引都從1開始
4.傳遞給lua腳本的的鍵和參數(shù):傳遞給lua腳本的鍵列表應(yīng)該包括可能會讀取或者寫入的所有鍵懈涛。傳入全部的鍵使得在使用各種分片或者集群技術(shù)時逛万,其他軟件可以在應(yīng)用層檢查所有的數(shù)據(jù)是不是都在同一個分片里面。另外集群版redis也會對將要訪問的key進行檢查批钠,如果不在同一個服務(wù)器里面宇植,那么redis將會返回一個錯誤得封。(決定使用集群版之前應(yīng)該考慮業(yè)務(wù)拆分),參數(shù)列表無所謂当纱。呛每。
5.lua腳本跟單個redis命令和事務(wù)段一樣都是原子的已經(jīng)進行了數(shù)據(jù)寫入的lua腳本將無法中斷,只能使用SHUTDOWN NOSAVE殺死Redis服務(wù)器坡氯,所以lua腳本一定要測試好晨横。
以上為個人理解,如有誤歡迎各位指正