当前位置: 代码网 > it编程>编程语言>Java > SpringBoot整合Redisson实现分布式锁的最佳实践

SpringBoot整合Redisson实现分布式锁的最佳实践

2026年08月06日 Java 我要评论
自己用 redis setnx 实现的分布式锁有各种坑(锁续期、误删、非原子)。redisson 是官方推荐的分布式锁方案,开箱即用。一、引入依赖<dependency> <g

自己用 redis setnx 实现的分布式锁有各种坑(锁续期、误删、非原子)。redisson 是官方推荐的分布式锁方案,开箱即用。

一、引入依赖

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

二、配置

@configuration
public class redissonconfig {

    @bean
    public redissonclient redissonclient() {
        config config = new config();
        config.usesingleserver()
            .setaddress("redis://localhost:6379");
        return redisson.create(config);
    }
}

三、基础用法

@service
public class seckillservice {

    @autowired
    private redissonclient redissonclient;

    @autowired
    private stringredistemplate redistemplate;

    public resultvo<?> seckill(long productid, long userid) {
        string lockkey = "lock:seckill:" + productid;
        rlock lock = redissonclient.getlock(lockkey);

        // 尝试获取锁,最多等3秒,锁自动续期
        boolean locked = false;
        try {
            locked = lock.trylock(3, 30, timeunit.seconds);
            if (!locked) {
                return resultvo.error(429, "操作太频繁,请稍后重试");
            }
            // 业务逻辑
            return doseckill(productid, userid);
        } catch (interruptedexception e) {
            return resultvo.error(500, "系统异常");
        } finally {
            // 释放锁(只有持有锁的线程能释放)
            if (locked && lock.isheldbycurrentthread()) {
                lock.unlock();
            }
        }
    }
}

四、注解式锁

@target(elementtype.method)
@retention(retentionpolicy.runtime)
public @interface redissonlock {
    /** 锁的key(支持spel) */
    string key();
    /** 等待锁时间 */
    long waittime() default 3;
    /** 锁过期时间 */
    long leasetime() default 30;
}
@aspect
@component
public class redissonlockaspect {

    @autowired
    private redissonclient redissonclient;

    @around("@annotation(lock)")
    public object around(proceedingjoinpoint pjp, redissonlock lock) throws throwable {
        string key = parsekey(lock.key(), pjp);
        rlock rlock = redissonclient.getlock(key);

        boolean locked = rlock.trylock(lock.waittime(), lock.leasetime(), timeunit.seconds);
        if (!locked) {
            throw new businessexception(429, "操作太频繁");
        }
        try {
            return pjp.proceed();
        } finally {
            if (rlock.isheldbycurrentthread()) {
                rlock.unlock();
            }
        }
    }
}

五、可重入锁

// redisson 的锁是可重入的
// 同一个线程可以多次获取同一个锁
public void methoda() {
    rlock lock = redissonclient.getlock("lock:test");
    lock.lock();
    methodb();  // 内部再次获取同一个锁,不会死锁
    lock.unlock();
}

public void methodb() {
    rlock lock = redissonclient.getlock("lock:test");
    lock.lock();
    // 业务逻辑
    lock.unlock();
}

六、公平锁

// 公平锁:按请求顺序获取锁
rlock fairlock = redissonclient.getfairlock("lock:fair");

七、读写锁

// 读锁:多个线程可同时读
// 写锁:独占
rreadwritelock rwlock = redissonclient.getreadwritelock("lock:rw");

rlock readlock = rwlock.readlock();   // 读锁
rlock writelock = rwlock.writelock(); // 写锁

八、redisson vs 手写 setnx

特性手写 setnxredisson
锁续期❌ 自己实现✅ 自动续期
释放校验❌ 可能误删✅ 校验线程
可重入
公平锁
读写锁
看门狗

九、看门狗机制

// redisson 的锁默认使用看门狗(watchdog)
// 如果业务执行时间超过锁的过期时间(默认30秒),看门狗会自动续期
// 每 10 秒续期一次,直到业务完成释放锁

// 注意:只有不指定 leasetime 时看门狗才生效
rlock lock = redissonclient.getlock("lock:test");
lock.lock();  // 不指定leasetime → 看门狗生效

十、秒杀场景最佳实践

@service
public class seckillservice {

    @redissonlock(key = "seckill:#productid", waittime = 3, leasetime = 30)
    public resultvo<?> doseckill(@pathvariable long productid, long userid) {
        // 前置校验
        seckillproduct product = productservice.getbyid(productid);
        if (product == null || product.getstatus() != 1) {
            return resultvo.error(404, "商品不存在");
        }
        // 时间校验
        localdatetime now = localdatetime.now();
        if (now.isbefore(product.getseckillstart())) {
            return resultvo.error(400, "秒杀未开始");
        }
        // 库存扣减
        int rows = productmapper.decrementstock(productid);
        if (rows == 0) {
            return resultvo.error(400, "库存不足");
        }
        // 创建订单
        return resultvo.success("秒杀成功");
    }
}

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

(0)

相关文章:

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

发表评论

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