高並發情況下對緩存進行讀取-修改操作時,需要原子性操作,Redis本身提供一個一些命令,例如incrby、hincrby自增(減)命令,但是這些命令在有些業務中不適用,這種情況下就可以使用lua腳本來實現多命令的執行(讀、寫);
以下lua腳本,通常lua腳本只需要加載一次,然后使用redis返回的hash值進行操作;
local local = redis.call('exists', KEYS[1]) if tonumber(local) == 0 then return false end if tonumber(redis.call('get', KEYS[1])) <= 0 then return false end if tonumber(ARGV[1]) > 0 then redis.call('incrby', KEYS[1], ARGV[1]) return true else if tonumber(redis.call('get', KEYS[1])) >= tonumber(ARGV[1]) then redis.call('incrby', KEYS[1], ARGV[1]) return true else return
false
end end
該腳本實現了對庫存的讀取和修改,該腳本可以在resources文件夾進行統一管理;
在java代碼中:
try { DefaultRedisScript<Boolean> redisScript = new DefaultRedisScript<>(); redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("/limit.lua"))); redisScript.setResultType(Boolean.class); return redisTemplate.execute(redisScript, Collections.singletonList(key), String.valueOf(mlitimes), String.valueOf(maxCount)); } catch (IOException e) { e.printStackTrace(); }
重點:在集群模式下,如果只在某個節點上傳了腳本,在其他節點中會找不到,因此需要判斷腳本是否存在,如果不存在,重新上傳lua腳本。