1. 程式人生 > 其它 >基於Redis實現分散式鎖之防誤刪非自己的鎖(lua版本)

基於Redis實現分散式鎖之防誤刪非自己的鎖(lua版本)

使用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"); // } } }