spring boot 下 Redisson分布式锁框架简单使用

本文介绍如何使用Redisson框架在Spring Boot项目中实现分布式锁,包括配置、接口定义及其实现,以及通过单元测试验证其有效性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在项目中要用到分布式锁,之前都是用jedis去实现的,有很多细节方面都有可能出问题,然后在了解到了redisson之后,决定使用这个成熟的框架去实现分布式锁。

首先引入jar包,除了spring boot的相关jar包,只引这一个就够了

            <dependency>
                <groupId>org.redisson</groupId>
                <artifactId>redisson</artifactId>
                <version>3.9.1</version>
            </dependency>

创建一个redis配置类

@Data
@ConfigurationProperties(prefix ="redisson")
public class RedissonProperties {

	/** redis地址  */
	private String address;
	
	/** 密码  */
	private String password;
	
	// 毫秒
	private int timeout=10000;
	
	private int database=0;
	
	private int connectionPoolSize=150;
	
	private int connectionMiniumIdleSize=10;
	
	// 毫秒
	private int scanInterval=2000;
}

在配置文件中,声明相对应的属性

#redisson的redis地址 单点
redisson.address=redis://redis-master.fn-data-platform:6379
redisson.password=agnYqD2fih

之后写一个config把redisson注册到spring中就可以了,这里使用的是单点redis模式,建议用于锁的redis和用于缓存的redis要分开,用于锁的要保证HA。

/**
 * @program: common-info
 * @description: redisson 配置类
 * @author: lvqiushi
 * @create: 2019-05-05 10:41
 **/
@Configuration
@EnableConfigurationProperties({ RedissonProperties.class })
public class RedissonConfig {
	@Autowired
	private RedissonProperties redissonProperties;

	@Bean
	@ConditionalOnProperty(name = "redisson.address")
	public RedissonClient redissonSingle(){
		Config config = new Config();
		SingleServerConfig serverConfig = config.useSingleServer()
				.setAddress(redissonProperties.getAddress())
				.setTimeout(redissonProperties.getTimeout())
				.setDatabase(redissonProperties.getDatabase())
				.setConnectionPoolSize(redissonProperties.getConnectionPoolSize())
				.setConnectionMinimumIdleSize(redissonProperties.getConnectionMiniumIdleSize())
				.setKeepAlive(true);
		if(StringUtils.isNotEmpty(redissonProperties.getPassword())){
			serverConfig.setPassword(redissonProperties.getPassword());
		}
		return Redisson.create(config);
	}
}

配置完成后,即可开始使用,我写了一个很简单的包装服务类,只用到了RLock可重入锁,redisson的锁有很多种类型,这个大家自己去学习了解。

/**
 *
 * @description: 分布式锁相关服务接口
 * @author: xiucai
 * @create: 2019-05-05
 *
 **/
public interface DistributedLock {

	/**
	 * @Description: 获取锁
	 * @param lockKey
	 * @return: org.redisson.api.RLock
	 * @Author: lvqiushi
	 * @Date: 2019-05-05
	 */
	RLock getLock(String lockKey);
	
	/**
	 * @Description: 使用默认超时时间设置锁 默认时间30s
	 * @param lockKey
	 * @return: org.redisson.api.RLock
	 * @Author: lvqiushi
	 * @Date: 2019-05-05
	 */
	RLock lock(String lockKey);

	/**
	 * @Description: 为锁设置超时时间
	 * @param lockKey
 	 * @param leaseTime 锁自动失效时间 单位:豪秒
	 * @return: org.redisson.api.RLock
	 * @Author: lvqiushi
	 * @Date: 2019-05-05
	 */
	RLock lock(String lockKey, int leaseTime);

	/** 
	 * @Description:  尝试获取锁,在等待时间内获取到锁则返回true,否则返回false,如果获取到锁,在指定超时时间释放锁
	 * @param lockKey
	 * @param waitTime	等到最大时间,强制获取锁
	 * @param leaseTime	 锁自动失效时间
	 * @return: boolean 
	 * @Author: lvqiushi 
	 * @Date: 2019-05-05 
	 */
	boolean tryLock(String lockKey, int waitTime, int leaseTime);

	/** 
	 * @Description: 释放锁
	 * @param lockKey	 
	 * @return: void 
	 * @Author: lvqiushi 
	 * @Date: 2019-05-05 
	 */
	void unlock(String lockKey);
}

然后是服务接口实现类,在实现类中引入在config中声明的bean

@Slf4j
@Component
public class DistributedLockImpl implements DistributedLock {
	@Autowired
	private RedissonClient redissonClient;
	
	@Override
	public RLock getLock(String lockKey) {
		RLock lock = redissonClient.getLock(lockKey);
		return lock;
	}
	
	@Override
	public RLock lock(String lockKey) {
		RLock lock = redissonClient.getLock(lockKey);
		lock.lock();
		return lock;
	}

	@Override
	public RLock lock(String lockKey, int leaseTime) {
		RLock lock = redissonClient.getLock(lockKey);
		lock.lock(leaseTime, TimeUnit.MILLISECONDS);
		return lock;
	}

	@Override
	public boolean tryLock(String lockKey, int waitTime, int leaseTime) {
		RLock lock = redissonClient.getLock(lockKey);
		try {
			return lock.tryLock(waitTime,leaseTime,TimeUnit.MILLISECONDS);
		} catch (InterruptedException e) {
			log.error("", e);
		}
		return false;
	}

	@Override
	public void unlock(String lockKey) {
		RLock lock = redissonClient.getLock(lockKey);
		lock.unlock();
	}
}

再写一个单元测试,用于测试redisson是否真的有效,具体实现就是使用N个线程进行自增num,然后判断num加的是否正确

    @Autowired
    private DistributedLock distributedLock;

    private int num = 0;

    /**
     * @Description: 分布式锁测试方法
     * @param
     * @return: void
     * @Author: lvqiushi
     * @Date: 2020-07-27
     */
    @Test
    public void lockTest() throws Exception {
        int threadCount = 20;
        CountDownLatch latch = new CountDownLatch(20);

        Runnable incr = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 50; i++) {
                    RLock lock = distributedLock.lock("cheat-test-lock-key", 3000);
                    num++;
                    System.out.println(num);
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    if (lock != null) {
                        lock.unlock();
                    }
                }

                latch.countDown();
            }
        };

        for (int i = 0; i < threadCount; i++) {
            new Thread(incr).start();
        }

        // 等所有计数加完
        latch.await();
        assert num == threadCount * 50;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值