首先我们要正确的理解 Redisson 应该什么时候应用 , 应该怎么用 , 相关资料自行查询
我们直接上代码:
1 pom加依赖
<dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.7.3</version> </dependency>
2 构建相关配置
此事要注意 我们要根据项目实际选择使用那种模式 是哨兵 还是正常模式,如果是正常模式我建议 把manager 交给 spring管理
通过注入的方式直接拿到 client , 如果是哨兵模式 建议 使用单利模式获取 相关 client
@Configuration public class RedissonManager { @Value("${redisson.address}") private String addressUrl; @Bean public RedissonClient getRedisson() throws Exception{ RedissonClient redisson = null; Config config = new Config(); config.useSingleServer() .setAddress("redis://"+addressUrl); redisson = Redisson.create(config); System.out.println(redisson.getConfig().toJSON().toString()); return redisson; } }
大家可以看到需要 一个redis地址 地址举例 127.0.0.1:6379
关于锁的操作我们封装一个 接口
public interface DistributedLocker { RLock lock(String lockKey); RLock lock(String lockKey, long timeout); RLock lock(String lockKey, TimeUnit unit, long timeout); boolean tryLock(String lockKey, TimeUnit unit, long waitTime, long leaseTime); void unlock(String lockKey); void unlock(RLock lock); }
并同时编写实现
@Component public class RedissonDistributedLocker implements DistributedLocker{ @Autowired private RedissonClient redissonClient; // RedissonClient已经由配置类生成,这里自动装配即可 // lock(), 拿不到lock就不罢休,不然线程就一直block @Override public RLock lock(String lockKey) { RLock lock = redissonClient.getLock(lockKey); lock.lock(); return lock; } // leaseTime为加锁时间,单位为秒 @Override public RLock lock(String lockKey, long leaseTime) { RLock lock = redissonClient.getLock(lockKey); lock.lock(leaseTime, TimeUnit.SECONDS); return lock; } // timeout为加锁时间,时间单位由unit确定 @Override public RLock lock(String lockKey, TimeUnit unit, long timeout) { RLock lock = redissonClient.getLock(lockKey); lock.lock(timeout, unit); return lock; } @Override public boolean tryLock(String lockKey, TimeUnit unit, long waitTime, long leaseTime) { RLock lock = redissonClient.getLock(lockKey); try { return lock.tryLock(waitTime, leaseTime, unit); } catch (InterruptedException e) { return false; } } @Override public void unlock(String lockKey) { RLock lock = redissonClient.getLock(lockKey); lock.unlock(); } @Override public void unlock(RLock lock) { lock.unlock(); } }
如此准备工作已就绪 那我们谈谈如何应用
使用前注入接口
@Autowired private DistributedLocker distributedLocker;
public Map<String, Object> test(Param param) { System.out.println("--------------init1111-----"+Thread.currentThread().getId()); String fuelNoLock = "fuelNoLock"; RLock lock = null; try { //分布式锁 lock = distributedLocker.lock(fuelNoLock,10L); System.out.println("--------------加锁-----"+Thread.currentThread().getId()); if(lock.tryLock()){ // TODO System.out.println("--------------持有锁-----"+Thread.currentThread().getId()); // 业务处理 //解锁 distributedLocker.unlock(lock); lock = null; System.out.println("--------------解锁-----"+Thread.currentThread().getId()); }else{ lock =null; System.out.println("--------------没锁-----"+Thread.currentThread().getId()); return null; } return null; } catch (Exception e) { e.printStackTrace(); } finally { if(lock != null){ if(lock.tryLock()) distributedLocker.unlock(lock); }else{ try { distributedLocker.unlock(fuelNoLock); } catch (Exception e) { System.out.println("1111111111111111"); } } } return null; }
以上是应用过程 其实对应用中 会有疑问 到底是业务处理完解锁 还是 finally中解锁 , 根据 实际情况测试 finally 中 才是正确的选择