当前位置: 代码网 > it编程>数据库>Redis > SpringBoot3+Redis实现分布式锁的配置方法

SpringBoot3+Redis实现分布式锁的配置方法

2024年09月07日 Redis 我要评论
springboot3+redis+lua脚本实现分布式锁相关依赖包<spring-boot.version>3.0.2</spring-boot.version><de

springboot3+redis+lua脚本实现分布式锁 

相关依赖包

<spring-boot.version>3.0.2</spring-boot.version>
<dependency>
    <groupid>org.springframework.boot</groupid>
    <artifactid>spring-boot-starter-web</artifactid>
</dependency>
<dependency>
    <groupid>org.springframework.boot</groupid>
    <artifactid>spring-boot-starter-data-redis</artifactid>
</dependency>

application.yml redis配置

spring:
  data:
    redis:
      host: 192.168.5.133
      port: 6379
      password:
      database: 0
      lettuce:
        pool:
          max-active: 8
          max-idle: 8
          min-idle: 0
          max-wait: "-1ms"

lua脚本

获取锁脚本 trylock.lua

-- keys[1] 是锁的键
-- argv[1] 是请求id
-- argv[2] 是锁的过期时间(秒)
local lockkey = keys[1]
local requestid = argv[1]
local expiretime = tonumber(argv[2])
-- 尝试获取锁
local lockvalue = redis.call('get', lockkey)
-- 如果锁不存在,尝试设置锁
if not lockvalue then
    if redis.call('setnx', lockkey, requestid) then
        -- 设置锁的过期时间
        redis.call('expire', lockkey, expiretime)
        return 1
    end
    return 0
elseif lockvalue == requestid then
    -- 如果请求id与当前锁持有者匹配,延长锁的过期时间
    redis.call('expire', lockkey, expiretime)
    return 1
else
    -- 锁被其他请求持有,无法获取锁
    return 0
end

释放锁脚本 releaselock.lua

-- keys[1] 是锁的键
-- argv[1] 是请求id
local lockkey = keys[1]
local requestid = argv[1]
-- 获取锁的值
local lockvalue = redis.call('get', lockkey)
-- 检查请求id是否匹配锁的持有者
if lockvalue == requestid then
    -- 删除锁
    redis.call('del', lockkey)
    return 1
else
    return 0
end

service层实现

package pub.qingyun.service;
import jakarta.annotation.resource;
import lombok.extern.slf4j.slf4j;
import org.springframework.core.io.classpathresource;
import org.springframework.data.redis.core.stringredistemplate;
import org.springframework.data.redis.core.script.defaultredisscript;
import org.springframework.scripting.support.resourcescriptsource;
import org.springframework.stereotype.service;
import java.util.list;
/**
 * @author cqy
 * @version 1.0
 * @date 2024/7/10 10:29
 **/
@service
@slf4j
public class redislockservice {
    private static final string lock_key = "distributed-lock";
    @resource
    private stringredistemplate stringredistemplate;
    private static final defaultredisscript<long> try_lock_script = new defaultredisscript<>();
    private static final defaultredisscript<long> release_lock_script = new defaultredisscript<>();
    static {
        try_lock_script.setscriptsource(new resourcescriptsource(new classpathresource("script/trylock.lua")));
        try_lock_script.setresulttype(long.class);
        release_lock_script.setscriptsource(new resourcescriptsource(new classpathresource("script/releaselock.lua")));
        release_lock_script.setresulttype(long.class);
    }
    /**
     * 尝试获取分布式锁。
     *
     * @param requestid  请求id,用于唯一标识锁的持有者。
     * @param expiretime 锁的过期时间(秒)。
     * @return 如果成功获取锁返回true,否则返回false。
     */
    public boolean trylock(string requestid, int expiretime) {
        object result = stringredistemplate.execute(try_lock_script,
                list.of(lock_key),
                requestid,
                string.valueof(expiretime));
        assert result != null;
        return long.parselong(result.tostring()) == 1l;
    }
    /**
     * 释放分布式锁。
     *
     * @param requestid 请求id,必须与获取锁时使用的相同。
     * @return 如果锁成功释放返回true,否则返回false。
     */
    public boolean releaselock(string requestid) {
        object result = stringredistemplate.execute(release_lock_script,
                list.of(lock_key),
                requestid);
        assert result != null;
        return long.parselong(result.tostring()) == 1l;
    }
}

controller调用示例代码

package pub.qingyun.controller;
import lombok.extern.slf4j.slf4j;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.web.bind.annotation.getmapping;
import org.springframework.web.bind.annotation.restcontroller;
import pub.qingyun.service.redislockservice;
import java.util.uuid;
import java.util.concurrent.timeunit;
/**
 * @author cqy
 * @version 1.0
 * @date 2024/7/10 10:43
 **/
@slf4j
@restcontroller
public class lualockcontroller {
    // lock timeout in seconds
    private static final int lock_timeout_seconds = 30000;
    private final redislockservice lockservice;
    @autowired
    public lualockcontroller(redislockservice lockservice) {
        this.lockservice = lockservice;
    }
    /**
     * 尝试获取锁并执行一些操作,然后释放锁。
     * 通过尝试获取锁来确保操作的原子性,避免并发问题
     */
    @getmapping("/performoperation")
    public string performoperation() {
        // 使用uuid作为请求id
        string requestid = uuid.randomuuid().tostring();
        try {
            // 尝试获取锁
            boolean trylock = lockservice.trylock(requestid, lock_timeout_seconds);
            log.info("获取锁[{}][{}]", requestid, trylock);
            if (trylock) {
                // 执行关键操作
                log.info("开始执行主任务[{}]...", requestid);
                timeunit.seconds.sleep(5); // 模拟耗时操作
                log.info("任务[{}]执行完成", requestid);
                return requestid + " completed successfully.";
            } else {
                log.info("无法获取锁,任务[{}]被拒绝", requestid);
                return "无法获取锁,任务[" + requestid + "]被拒绝";
            }
        } catch (interruptedexception e) {
            thread.currentthread().interrupt();
            log.error("interrupted while performing operation.", e);
            return "任务[" + requestid + "]执行失败";
        } finally {
            // 释放锁
            boolean releaselock = lockservice.releaselock(requestid);
            log.info("释放锁[{}][{}]", requestid, releaselock);
        }
    }
}

springboot3+redisson实现分布式锁

添加依赖包

<dependency>
    <groupid>org.redisson</groupid>
    <artifactid>redisson-spring-boot-starter</artifactid>
    <version>3.20.0</version>
</dependency>

配置类

@configuration
package pub.qingyun.config;
import org.redisson.redisson;
import org.redisson.api.redissonclient;
import org.redisson.config.config;
import org.springframework.beans.factory.annotation.value;
import org.springframework.context.annotation.bean;
import org.springframework.context.annotation.configuration;
import org.springframework.data.redis.connection.redisconnectionfactory;
import org.springframework.data.redis.core.redistemplate;
import org.springframework.data.redis.serializer.genericjackson2jsonredisserializer;
import org.springframework.data.redis.serializer.stringredisserializer;
/**
 * @author cqy
 * @version 1.0
 * @date 2024/7/5 10:58
 **/
@configuration
public class redisconfig {
    @value("${spring.data.redis.host}")
    private string host;
    @value("${spring.data.redis.port}")
    private string port;
    @bean
    public redissonclient redissonclient() {
        config config = new config();
        config.usesingleserver().setaddress("redis://" + host + ":" + port + "");
        return redisson.create(config);
    }
    @bean
    public redistemplate<string, object> redistemplate(redisconnectionfactory connectionfactory) {
        redistemplate<string, object> template = new redistemplate<>();
        template.setconnectionfactory(connectionfactory);
        template.setkeyserializer(new stringredisserializer());
        template.setvalueserializer(new genericjackson2jsonredisserializer());
        template.afterpropertiesset();
        return template;
    }
}

实现类

 	@resource
    private redissonclient redissonclient;
	public void example() {
        rlock rlock = redissonclient.getlock("mylock");
        try {
            boolean locked = rlock.trylock(0, 800, timeunit.milliseconds);
            if (locked) {
                // todo
            } else {
                log.warn("thread[{}]could not acquire lock.", thread.currentthread().getname());
            }
        } catch (interruptedexception e) {
            thread.currentthread().interrupt();
            log.error("error occurred while trying to acquire lock.", e);
        } finally {
            if (rlock.isheldbycurrentthread()) {
                rlock.unlock();
            }
        }
    }

到此这篇关于springboot3+redis实现分布式锁的文章就介绍到这了,更多相关springboot3 redis分布式锁内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com