风止雨歇

Redisson 的分布式锁

参考:https://www.cnblogs.com/zgq7/p/14746128.html

一、Redisson 的使用

1、Redisson 的简单使用

(1)引入maven坐标;

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>3.13.4</version>
</dependency>

 

(2)增加配置文件,将Redisson注入到容器中;

@Configuration
public class RedissonConfig {
 
    @Bean
    public Redisson redisson() {
        Config config = new Config();
        //单机版
        //config.useSingleServer().setAddress("redis://192.168.1.1:8001").setDatabase(0);
 
        //集群版
        config.useClusterServers()
                .addNodeAddress("redis://192.168.1.1:8001")
                .addNodeAddress("redis://192.168.1.1:8002")
                .addNodeAddress("redis://192.168.1.2:8001")
                .addNodeAddress("redis://192.168.1.2:8002")
                .addNodeAddress("redis://192.168.1.3:8001")
                .addNodeAddress("redis://192.168.1.3:8002");
        return (Redisson) Redisson.create(config);
    }
}

 

(3)分布式锁的实现

@Service
public class RedisLockDemo {
    @Autowired
    private StringRedisTemplate redisTemplate;
 
    @Autowired
    private Redisson redisson;
 
    public String deduceStock() {
        String lockKey = "lockKey";
        RLock redissonLock = redisson.getLock(lockKey);
 
        try {
            //加锁, 实现锁续命的功能(加锁成功,后台启动一个timer, 默认每10s检测一次是否持有锁,若持有锁则继续续命30s)
            redissonLock.lock();
 
            //------ 执行业务逻辑 ----start------
            int stock = Integer.valueOf(redisTemplate.opsForValue().get("stock"));
            if (stock > 0) {
                int newStock = stock - 1;
                //执行业务操作减库存
                redisTemplate.opsForValue().set("stock", newStock + "");
                System.out.println("扣减库存成功, 剩余库存:" + newStock);
            } else {
                System.out.println("库存已经为0,不能继续扣减");
            }
            //------ 执行业务逻辑 ----end------
        } finally {
            //解锁
            redissonLock.unlock();
        }
        return "success";
    }
}

 

2、Redisson 的几种加锁方式

/*
 *  (1) T1加锁成功: 会添加TimerTask; 每10s执行一次检测锁是否为当前线程占用, 若占用, 则将key超时时间重置为30s;
 *  (2) T2加锁失败后会不停的去重试;
 */
redissonLock.lock();

/*
 *  (1) T1加锁成功后直接返回, 20s后锁自动过期; (没有watch dog)
 *  (2) T2加锁失败后会不停的去重试;
 */
redissonLock.lock(20, TimeUnit.SECONDS);

/*
 *  (1) T1尝试加锁成功, 返回true; 会添加TimerTask; 每10s执行一次检测锁是否为当前线程占用, 若占用, 则将key超时时间重置为30s;
 *  (2) T2没有获取到锁会不停的去重试, 在50s后停止重试, 返回false;
 */
boolean isGetLock = redissonLock.tryLock(50, TimeUnit.SECONDS);

/*
 *  (1) T1尝试加锁成功, 返回true, 锁在20s后自动过期; (没有watch dog)
 *  (2) T2尝试加锁失败, 在50s后停止重试, 返回false;
 */
boolean isGetLock = redissonLock.tryLock(50, 20, TimeUnit.SECONDS);

//-------------------------------------------------------------

//2. 公平锁 保证 Redisson 客户端线程将以其请求的顺序获得锁
RLock fairLock = redissonClient.getFairLock("fairLock");

//3. 读写锁 没错与JDK中ReentrantLock的读写锁效果一样
RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("readWriteLock");
readWriteLock.readLock().lock();
readWriteLock.writeLock().lock();

 

二、Redisson 的分布式锁原理

 

 Redisson 的加锁和解锁都通过 lua 脚本来处理的;

三、Redisson的分布式锁源码分析

 

posted on 2022-03-09 22:46  风止雨歇  阅读(744)  评论(0编辑  收藏  举报

导航