分布式锁实现----Redis+Lua脚本

说明:

每个lua 脚本中的操作都是原子操作

实现步骤

在resources目录下新建 lua 脚本

  • /resources/luascript/lock-del.lua
    1
    2
    3
    4
    5
    if redis.call("get",KEYS[1])==ARGV[1] then
    return redis.call("del",KEYS[1])
    else
    return 0
    end
  • /resources/luascript/lock-set.lua
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    --- 获取key
    local key = KEYS[1]
    --- 获取value
    local val = KEYS[2]
    --- 获取一个参数
    local expire = ARGV[1]
    --- 如果redis找不到这个key就去插入
    if redis.call("get", key) == false then
    --- 如果插入成功,就去设置过期值
    if redis.call("set", key, val) then
    --- 由于lua脚本接收到参数都会转为String,所以要转成数字类型才能比较
    if tonumber(expire) > 0 then
    --- 设置过期时间
    redis.call("expire", key, expire)
    end
    return true
    end
    return false
    else
    return false
    end

    Lua 配置类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    @Configuration
    public class LuaConfiguration {
    @Bean(name = "set")
    public DefaultRedisScript<Boolean> redisScript() {
    DefaultRedisScript<Boolean> redisScript = new DefaultRedisScript<>();
    redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("luascript/lock-set.lua")));
    redisScript.setResultType(Boolean.class);
    return redisScript;
    }

    @Bean(name = "del")
    public DefaultRedisScript<Boolean> redisScriptDel() {
    DefaultRedisScript<Boolean> redisScript = new DefaultRedisScript<>();
    redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("luascript/lock-del.lua")));
    redisScript.setResultType(Boolean.class);
    return redisScript;
    }
    }

    controller

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    @RestController
    public class LuaLockController {
    @Resource(name = "set")
    private DefaultRedisScript<Boolean> redisScript;
    @Resource(name = "del")
    private DefaultRedisScript<Boolean> redisScriptDel;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @GetMapping("/lua")
    public ResponseEntity lua() {
    List<String> keys = Arrays.asList("testLua", "hello lua");
    Boolean execute = stringRedisTemplate.execute(redisScript, keys, "100");
    return null;
    }

    @GetMapping("/lua-del")
    public ResponseEntity luaDel() {
    List<String> keys = Arrays.asList("testLua");
    Boolean execute = stringRedisTemplate.execute(redisScriptDel, keys,"hello lua");
    return null;
    }
    }

分布式锁实现----Redis+Lua脚本
http://yoursite.com/post/b6642ebe.html/
Author
Chase Wang
Posted on
December 1, 2021
Licensed under