1.Redisson介绍wiki:https://github.com/redisson/redisson/wiki/
2.整合Spingboot实现分布式锁:
application.properties配置redis地址:
redisson.address=redis://*.*.*.*:6379
redisson.password=123456
Redisson相关配置及工具类:
package com.demo.distributedlock.redis;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* @author libo
* @ClassName RedissonProperties
* @Description: RedissonPropertis配置
* @date 2018/11/16 16:55
*/
@ConfigurationProperties(prefix="redisson")
public class RedissonProperties {
private int timeout = 3000;
private String address;
private String password;
private int connectionPoolSize = 64;
private int connectionMinimumIdleSize=10;
private int slaveConnectionPoolSize = 250;
private int masterConnectionPoolSize = 250;
private String[] sentinelAddresses;
private String masterName;
public int getTimeout() {
return timeout;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public int getSlaveConnectionPoolSize() {
return slaveConnectionPoolSize;
}
public void setSlaveConnectionPoolSize(int slaveConnectionPoolSize) {
this.slaveConnectionPoolSize = slaveConnectionPoolSize;
}
public int getMasterConnectionPoolSize() {
return masterConnectionPoolSize;
}
public void setMasterConnectionPoolSize(int masterConnectionPoolSize) {
this.masterConnectionPoolSize = masterConnectionPoolSize;
}
public String[] getSentinelAddresses() {
return sentinelAddresses;
}
public void setSentinelAddresses(String sentinelAddresses) {
this.sentinelAddresses = sentinelAddresses.split(",");
}
public String getMasterName() {
return masterName;
}
public void setMasterName(String masterName) {
this.masterName = masterName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getConnectionPoolSize() {
return connectionPoolSize;
}
public void setConnectionPoolSize(int connectionPoolSize) {
this.connectionPoolSize = connectionPoolSize;
}
public int getConnectionMinimumIdleSize() {
return connectionMinimumIdleSize;
}
public void setConnectionMinimumIdleSize(int connectionMinimumIdleSize) {
this.connectionMinimumIdleSize = connectionMinimumIdleSize;
}
}
package com.demo.distributedlock.redis;
import org.apache.commons.lang3.StringUtils;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.config.SingleServerConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author libo
* @ClassName RedissonAutoConfiguration
* @date 2018/11/16 17:25
*/
@Configuration
@ConditionalOnClass(Config.class)
@EnableConfigurationProperties(RedissonProperties.class)
public class RedissonAutoConfiguration {
@Autowired
private RedissonProperties redissonProperties;
/***
* @Author libo
* @Description //单机模式自动装配
* @return
*/
@Bean
@ConditionalOnProperty(name = "redisson.address")
RedissonClient redissonSingle(){
Config config = new Config();
SingleServerConfig serverConfig = config.useSingleServer()
.setAddress(redissonProperties.getAddress())
.setTimeout(redissonProperties.getTimeout())
.setConnectionPoolSize(redissonProperties.getConnectionPoolSize())
.setConnectionMinimumIdleSize(redissonProperties.getConnectionMinimumIdleSize());
if(StringUtils.isNotBlank(redissonProperties.getPassword())) {
serverConfig.setPassword(redissonProperties.getPassword());
}
return Redisson.create(config);
}
/**
* 装配locker类,并将实例注入到RedissonLockUtil中
* @return
*/
@Bean
RedissLockUtil redissLockUtil(RedissonClient redissonClient){
RedissLockUtil redissLockUtil = new RedissLockUtil();
redissLockUtil.setRedissonClient(redissonClient);
return redissLockUtil;
}
}
package com.demo.distributedlock.redis;
import java.util.concurrent.TimeUnit;
import org.redisson.api.*;
/**
* @author libo
* @ClassName RedissLockUtil
* @Description: redisson 分布式锁工具类
* @date 2018/11/16 17:06
*/
public class RedissLockUtil {
private static RedissonClient redissonClient;
public void setRedissonClient(RedissonClient redissonClient){
this.redissonClient = redissonClient;
}
/***
* @Author libo
* @Description //加锁
* @return org.redisson.api.RLock
*/
public static RLock getLock(String lockKey){
RLock lock = redissonClient.getLock(lockKey);
return lock;
}
/***
* @Author libo
* @Description //获取公平锁
* @return org.redisson.api.RLock
*/
public static RLock getFairLock(String lockKey){
RLock fairLock = redissonClient.getFairLock(lockKey);
return fairLock;
}
/***
* @Author libo
* @Description //获取读写锁
* @return org.redisson.api.RReadWriteLock
*/
public static RReadWriteLock getReadWriteLock(String lockKey){
RReadWriteLock rwlock = redissonClient.getReadWriteLock(lockKey);
return rwlock;
}
/***
* @Author libo
* @Description //获取信号量
* @return
*/
public static RSemaphore getSemaphore(String lockKey){
RSemaphore semaphore = redissonClient.getSemaphore(lockKey);
return semaphore;
}
/***
* @Author libo
* @Description //获取countDownLatch
* @return
*/
public static RCountDownLatch getCountDownLatch(String lockKey){
RCountDownLatch rCountDownLatch = redissonClient.getCountDownLatch(lockKey);
return rCountDownLatch;
}
/***
* @Author libo
* @Description //异步加锁
* @Date 15:03 2018/12/18
* @return org.redisson.api.RFuture
*/
public static RFuture tryLockAsync(String lockKey,int waitTime,int leaseTime,TimeUnit timeUnit) throws InterruptedException {
RLock lock = redissonClient.getLock(lockKey);
Thread.sleep(1000);
return lock.tryLockAsync(waitTime,leaseTime,timeUnit);
}
/***
* @Author libo
* @Description //释放锁
* @Date 17:12 2018/11/16
* @return void
*/
public static void unLock(String lockKey){
RLock lock = redissonClient.getLock(lockKey);
lock.unlock();
}
/***
* @Author libo
* @Description //释放锁
* @Date 17:12 2018/11/16
* @return void
*/
public static void unLock(RLock lock){
lock.unlock();
}
/***
* @Author libo
* @Description //带超时的锁 单位 秒
* @Date 17:17 2018/11/16
* @return org.redisson.api.RLock
*/
public static RLock lock(String lockKey,int timeout){
RLock lock = redissonClient.getLock(lockKey);
lock.lock(timeout, TimeUnit.SECONDS);
return lock;
}
public static RLock lock(String lockKey,TimeUnit timeUnit,int timeout){
RLock lock = redissonClient.getLock(lockKey);
lock.lock(timeout, timeUnit);
return lock;
}
/***
* @Author libo
* @param lockKey
* @param waitTime 最多等待时间
* @param leaseTime 上锁后自动释放锁时间
* @Date 17:20 2018/11/16
* @return boolean
*/
public static boolean tryLock(String lockKey,int waitTime, int leaseTime){
RLock lock = redissonClient.getLock(lockKey);
try {
return lock.tryLock(waitTime,leaseTime,TimeUnit.SECONDS);
} catch (InterruptedException e) {
return false;
}
}
/***
* @Author libo
* @param lockKey
* @param waitTime 最多等待时间
* @param leaseTime 上锁后自动释放锁时间
* @Date 17:20 2018/11/16
* @return boolean
*/
public static boolean tryLock(String lockKey,TimeUnit timeUnit, int waitTime, int leaseTime){
RLock lock = redissonClient.getLock(lockKey);
try {
return lock.tryLock(waitTime,leaseTime,timeUnit);
} catch (InterruptedException e) {
return false;
}
}
}
分布式锁测试测试类:
package com.example.demo;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.redisson.RedissonMultiLock;
import org.redisson.RedissonRedLock;
import org.redisson.api.*;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import com.demo.seckill.Application;
import com.demo.seckill.distributedlock.redis.RedissLockUtil;
/**
* @author libo
* @ClassName RedissonLockDemo
* @Description: 分布式锁demo
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class,webEnvironment = SpringBootTest.WebEnvironment.NONE)
@WebAppConfiguration
public class RedissonLockDemo {
/***
* @Author libo
* @Description // Redisson可重入锁测试,实现了java对象的lock接口
* @return
*/
@Test
public void testReentrantLock() throws InterruptedException {
RLock lock = RedissLockUtil.getLock("lockKey");
for (int i=0;i<3;i++){
new Thread(new Runnable() {
@Override
public void run() {
// 1. 最常见的使用方法
// lock.lock();
// 2. 支持过期解锁功能,10秒钟以后自动解锁, 无需调用unlock方法手动解锁
// lock.lock(10, TimeUnit.SECONDS);
// 3. 尝试加锁,最多等待3秒,上锁以后10秒自动解锁
try {
boolean res = lock.tryLock(3, 10, TimeUnit.SECONDS);
if(res){
System.out.println(Thread.currentThread().getName()+"线程获取锁成功");
//获得锁,执行业务
}else {
System.out.println(Thread.currentThread().getName()+"线程获取锁失败");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
//过期自动解锁,无需手动解锁
//lock.unlock();
Thread.sleep(10000);
}
/***
* @Author libo
* @Description // 为分布式锁提供异步执行的方法
* @return void
*/
@Test
public void testAsyncReentrantLock() throws InterruptedException {
new Thread(new Runnable() {
@Override
public void run() {
try {
/*lock.tryLockAsync();
//加锁10后自动解锁
lock.tryLockAsync(10, TimeUnit.SECONDS);
lock.tryLockAsync(3, 20, TimeUnit.SECONDS)*/
RFuture res = RedissLockUtil.tryLockAsync("getLock",3, 20, TimeUnit.SECONDS);
if(res.get()){
System.out.println("这个是获取到锁之后,异步调用的方法");
}
}catch (Exception e) {
e.printStackTrace();
}
}
}).start();
System.out.println("这是主线程的方法");
Thread.sleep(10000);
}
/**
* 公平锁(Fair Lock)
* Redisson分布式可重入公平锁也是实现了java.util.concurrent.locks.Lock接口的一种RLock对象。
* 在提供了自动过期解锁功能的同时,保证了当多个Redisson客户端线程同时请求加锁时,优先分配给先发出请求的线程。
* @param redisson
*/
@Test
public void testFairLock() throws InterruptedException {
RLock fairLock = RedissLockUtil.getFairLock("getLock");
new Thread(new MyRunner("线程A",fairLock)).start();
new Thread(new MyRunner("线程B",fairLock)).start();
Thread.sleep(10000);
}
/**
* 联锁(MultiLock)
* Redisson的RedissonMultiLock对象可以将多个RLock对象关联为一个联锁,
* 每个RLock对象实例可以来自于不同的Redisson实例
*/
@Test
public void testMultiLock(){
RLock lock1 = RedissLockUtil.getLock("lock1");
RLock lock2 = RedissLockUtil.getLock("lock2");
RLock lock3 = RedissLockUtil.getLock("lock3");
RedissonMultiLock multiLock = new RedissonMultiLock(lock1,lock2,lock3);
try{
//multiLock.lock();
//multiLock.lock(100,TimeUnit.SECONDS);
boolean res = multiLock.tryLock(10, 10, TimeUnit.SECONDS);
if(res){
System.out.println("这是联锁测试");
}
}catch (Exception e){
System.out.println("获取不到锁,发生异常");
e.printStackTrace();
}finally {
try{
multiLock.unlock();
}catch (Exception e){
System.out.println("获取不到锁,解锁发生异常");
}
}
}
@Test
public void testAlwaysLock() throws InterruptedException {
RLock lock = RedissLockUtil.getLock("lock1");
new Thread(new Runnable() {
@Override
public void run() {
// 1. 最常见的使用方法
// lock.lock();
// 2. 支持过期解锁功能,10秒钟以后自动解锁, 无需调用unlock方法手动解锁
// lock.lock(10, TimeUnit.SECONDS);
// 3. 尝试加锁,最多等待3秒,上锁以后10秒自动解锁
try {
boolean res = lock.tryLock();
if(res){
System.out.println(Thread.currentThread().getName()+"线程获取锁成功");
//获得锁,执行业务
}else {
System.out.println(Thread.currentThread().getName()+"线程获取锁失败");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
Thread.sleep(1000000);
}
/**
* 红锁(RedLock)
* Redisson的RedissonRedLock对象实现了Redlock介绍的加锁算法。
* 该对象也可以用来将多个RLock对象关联为一个红锁,每个RLock对象实例可以来自于不同的Redisson实例
*/
@Test
public void testRedLock(){
RLock lock1 = RedissLockUtil.getLock("lock1");
RLock lock2 = RedissLockUtil.getLock("lock2");
RLock lock3 = RedissLockUtil.getLock("lock3");
RedissonRedLock lock = new RedissonRedLock(lock1, lock2, lock3);
try {
// 同时加锁:lock1 lock2 lock3, 红锁在大部分节点上加锁成功就算成功。
lock.lock();
// 尝试加锁,最多等待100秒,上锁以后10秒自动解锁
boolean res = lock.tryLock(10, 10, TimeUnit.SECONDS);
if (res) {
System.out.println("这是红锁测试");
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
/***
* @Author libo
* @Description //读写锁测试
* @return
*/
@Test
public void testRWlock() throws InterruptedException {
RReadWriteLock rwlock = RedissLockUtil.getReadWriteLock("lockKey");
for (int i = 0; i < 3; i++) {
new Thread(new Runnable() {
@Override
public void run() {
try {
boolean redRes = rwlock.readLock().tryLock(5, 10, TimeUnit.SECONDS);
if(redRes){
System.out.println(Thread.currentThread().getName()+"线程获取读锁成功");
}else{
System.out.println(Thread.currentThread().getName()+"线程获取读锁失败");
}
boolean writeRes = rwlock.writeLock().tryLock(10, 10, TimeUnit.SECONDS);
if (writeRes){
System.out.println(Thread.currentThread().getName()+"线程获取写锁成功");
}else {
System.out.println(Thread.currentThread().getName()+"线程获取写锁失败");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
Thread.sleep(100000);
}
/***
* @Author libo
* @Description //信号量测试
* @return
*/
@Test
public void testSemaphore() throws InterruptedException {
RSemaphore semaphore = RedissLockUtil.getSemaphore("semaphore ");
semaphore.trySetPermits(10);
Driver driver = new Driver(semaphore);
for (int i = 0; i < 5; i++) {
(new Car(driver)).start();
}
Thread.sleep(10000);
}
/***
* @Author libo
* @Description //RCountDownLatch测试
* @return
*/
@Test
public void testCountDownLatch() throws InterruptedException {
RCountDownLatch countDownlatch = RedissLockUtil.getCountDownLatch("countDownlatch ");
countDownlatch.trySetCount(5);
Driver driver = new Driver(countDownlatch);
for (int i = 0; i < 5; i++) {
(new Car(driver)).start();
}
System.out.println("主线程阻塞,等待所有子线程执行完成");
//countDownlatch.await()使得主线程阻塞直到countDownlatch.countDown()为零才继续执行
countDownlatch.await();
System.out.println("所有线程执行完成!");
Thread.sleep(10000);
}
class MyRunner implements Runnable{
String threadName;
RLock rLock;
public MyRunner(String threadName,RLock rLock){
this.threadName = threadName;
this.rLock = rLock;
}
public String getThreadName() {
return threadName;
}
public void setThreadName(String threadName) {
this.threadName = threadName;
}
public RLock getrLock() {
return rLock;
}
public void setrLock(RLock rLock) {
this.rLock = rLock;
}
@Override
public void run() {
try{
/*
fairLock.lock();
// 支持过期解锁功能, 10秒钟以后自动解锁,无需调用unlock方法手动解锁
fairLock.lock(10, TimeUnit.SECONDS);*/
// 尝试加锁,最多等待100秒,上锁以后10秒自动解锁
boolean res = rLock.tryLock(100, 10, TimeUnit.SECONDS);
if (res) {
System.out.println("线程名称:"+getThreadName());
}
}catch (Exception e){
e.printStackTrace();
}
}
}
class Driver {
private RSemaphore semaphore;
private RCountDownLatch rCountDownLatch;
public Driver(RSemaphore semaphore){
this.semaphore = semaphore;
}
public Driver(RCountDownLatch rCountDownLatch){
this.rCountDownLatch = rCountDownLatch;
}
public void driveCar() {
try {
// 从信号量中获取一个允许机会
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + " start at " + System.currentTimeMillis());
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + " stop at " + System.currentTimeMillis());
// 释放允许,将占有的信号量归还
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void driveCar2() {
System.out.println( Thread.currentThread().getName() +" start at "+ System.currentTimeMillis());
// 每个独立子线程执行完后,countDownLatch值减1
rCountDownLatch.countDown();
}
}
class Car extends Thread{
private Driver driver;
public Car(Driver driver) {
super();
this.driver = driver;
}
public void run() {
//driver.driveCar();
driver.driveCar2();
}
}
}