lua操作redis

参考:https://blog.csdn.net/weixin_54721305/article/details/125648123

实现分布式锁

依赖

<dependencies>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter</artifactId>
          <version>2.2.1.RELEASE</version>
      </dependency>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
          <version>2.2.1.RELEASE</version>
      </dependency>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-data-redis</artifactId>
          <version>2.2.1.RELEASE</version>
      </dependency>
</dependencies>

application.properties

# 指定端口号
server.port=8199

# 连接redis
spring.redis.host=192.168.171.138
spring.redis.port=6379

config

/**
 * @Author 嘉宾
 * @Data 2022/7/6 20:37
 * @Version 1.0
 * @Description 用于声明lua
 */
@Configuration
public class LuaRedisConfig {

    /**
     * 分布式锁脚本
     * @return
     */
    @Bean
    public DefaultRedisScript<Long> lockRedisScript() {
        // 定义DefaultRedisScript
        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
        // 指定lua脚本路径
        redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("script/lock.lua")));
        // 设置返回类型
        redisScript.setResultType(Long.class);
        return redisScript;     // 返回lua脚本内容
    }
    
}

script

在resources目录下创建目录script目录在其目录下创建Lua脚本文件

local lockUUID = KEYS[1]    -- 锁中的uuid值
local uuid = ARGV[1]        -- 用户的uuid值

-- 判断锁中的uuid是否与用户的uuid相等
if redis.call('get',lockUUID) == uuid then
    return redis.call('del',lockUUID)   -- 相等的话就释放锁
else    -- 未获得锁
    return 0    -- 返回0
end

controller

/**
 * @Author 嘉宾
 * @Data 2022/7/6 20:39
 * @Version 1.0
 * @Description
 */
@RestController
@RequestMapping("/lua")
public class TestController {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private DefaultRedisScript<Boolean> lockRedisScript;    // 分布式锁脚本

    /**
     * 计数
     * @return
     */
    @GetMapping("/getLock")
    public String getLock(){
        // 生成UUID
        String uuid = UUID.randomUUID().toString();
        // 1、获取锁:true得到锁,false未得到
        Boolean redisLock = stringRedisTemplate.opsForValue().setIfAbsent("lock_redis", uuid,3, TimeUnit.SECONDS);
        // 判断是否得到锁
        if(redisLock){
            // ...自己的业务
            String value = stringRedisTemplate.opsForValue().get("num");
            if(StringUtils.isEmpty(value)){
                stringRedisTemplate.opsForValue().set("num","1");
            }
            int num = Integer.parseInt(value + "") + 1;
            stringRedisTemplate.opsForValue().set("num",num+"");
            // 获取锁中的内容
            String lockUUID = stringRedisTemplate.opsForValue().get("lock_redis");
            // 使用Lua脚本比较
            // 指定参数
            List<String> keys = Arrays.asList(lockUUID);
            stringRedisTemplate.execute(lockRedisScript,keys,uuid);
            return "success"+num;
        }else{
//            // 每隔0.1秒再获取一次
//            try {
//                Thread.sleep(100);
//                this.getLock();
//            }catch (InterruptedException e){
//                e.printStackTrace();
//            }
            return "miss";
        }
    }

}
posted @ 2023-09-14 11:13  hasome  阅读(52)  评论(0编辑  收藏  举报