基於Redis實現分散式鎖之防誤刪非自己的鎖(lua版本)
阿新 • • 發佈:2022-01-11
使用lua需要配置環境,但是Redis已經繼承了Lua,所以使用Redis可以不用安裝Lua指令碼,其本身提供了對lua的支援
主要通過 指令 eval script numKeys key.. arg..
redis輸出的不是lua指令碼的輸出,而是lua指令碼的的返回值
//基於 Redis 實現分散式鎖 public void testLock() { //加鎖 String uuid = UUID.randomUUID().toString(); Boolean lock = this.redisTemplate.opsForValue().setIfAbsent("lock", uuid,3,TimeUnit.SECONDS); //setIfAbsent 對應 setnx,只能設定為空的key if (!lock){ try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } this.testLock(); }else{ //設定過期時間 //this.redisTemplate.expire("lock",3,TimeUnit.MILLISECONDS);//獲取鎖,執行業務操作 String num = this.redisTemplate.opsForValue().get("num"); if (StringUtils.isBlank(num)){ this.redisTemplate.opsForValue().set("num","1"); return; } int i = Integer.parseInt(num); this.redisTemplate.opsForValue().set("num",String.valueOf(++i));//釋放鎖(使用lua指令碼) String script = "if redis.call('get',KEYS[1]) == ARGV[1]" + "then " + " retuen redis.call('del',KEYS[1]) " + "else " + " return 0 " + "end"; this.redisTemplate.execute(new DefaultRedisScript<>(script,Boolean.class), Arrays.asList("lock"),uuid); // if (StringUtils.equals(uuid,this.redisTemplate.opsForValue().get("lock"))){ // this.redisTemplate.delete("lock"); // } } }