实例代码地址,请前往:https://gitee.com/GuoqingLee/distributed-seckill
redis官方文档地址,请前往:http://www.redis.cn/topics/distlock.html
前言
关于分布式锁的实现,目前主流方案有以下三类:
1、基于数据库的乐观锁;
2、基于redis实现的锁服务;
3、基于zookeeper的实现;
网上关于怎么实现redis的分布式锁,一搜一大把的文章,有写的比较好的,也有明显存在缺陷的,非常容易误导初入这一块的初学者;
而存在的问题,无外乎是setnx()-->expire(),保证不了原子性,容易出现死锁等情况,这里就不在去做解释了;
本文的主旨是如何使用redis官方推荐的redisson实现redis的分布式锁;
一、具体实现:
maven引入需要的jar
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.10.1</version>
</dependency>
配置文件如下
# common spring boot settings spring.redis.database=
spring.redis.host=
spring.redis.port=
spring.redis.password=
spring.redis.ssl=
spring.redis.timeout=
spring.redis.cluster.nodes=
spring.redis.sentinel.master=
spring.redis.sentinel.nodes=
封装工具类:
package cn.com.bluemoon.redis.lock; import java.util.concurrent.TimeUnit; import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; /**
* 基于Redisson的分布式锁实现
* @author Guoqing.Lee
* @date 2019年1月23日 下午4:04:57
*
*/
@Component
public class RedissonDistributedLocker { @Autowired
private RedissonClient redissonClient; /**
* 加锁
* @param lockKey
* @return
*/
public RLock lock(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock();
return lock;
} /**
* 加锁,过期自动释放
* @param lockKey
* @param leaseTime 自动释放锁时间
* @return
*/
public RLock lock(String lockKey, long leaseTime) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock(leaseTime, TimeUnit.SECONDS);
return lock;
} /**
* 加锁,过期自动释放,时间单位传入
* @param lockKey
* @param unit 时间单位
* @param leaseTime 上锁后自动释放时间
* @return
*/
public RLock lock(String lockKey, TimeUnit unit, long leaseTime) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock(leaseTime, unit);
return lock;
} /**
* 尝试获取所
* @param lockKey
* @param unit 时间单位
* @param waitTime 最多等待时间
* @param leaseTime 上锁后自动释放时间
* @return
*/
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;
}
} /**
* 尝试获取所
* @param lockKey
* @param waitTime 最多等待时间
* @param leaseTime 上锁后自动释放锁时间
* @return
*/
public boolean tryLock(String lockKey, long waitTime, long leaseTime) {
RLock lock = redissonClient.getLock(lockKey);
try {
return lock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS);
} catch (InterruptedException e) {
return false;
}
} /**
* 释放锁
* @param lockKey
*/
public void unlock(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
lock.unlock();
} /**
* 释放锁
* @param lock
*/
public void unlock(RLock lock) {
lock.unlock();
} }
二、使用方式
方式一:
@Autowired
private RedissonDistributedLocker redissonDistributedLocker; String lockKey = "BM_MARKET_SECKILL_" + stallActivityId;
try {
//超过2S自动释放锁
redissonDistributedLocker.lock(lockKey, 2L);
//业务处理 } finally {
redissonDistributedLocker.unlock(lockKey); //释放锁
}
方案二:
@Autowired
private RedissonDistributedLocker redissonDistributedLocker; public void test() throws InterruptedException {
final int[] counter = {0}; for (int i= 0; i < 100; i++){ new Thread(new Runnable() { @Override public void run() {
boolean isGetLock = redissonDistributedLocker.tryLock("test0001", 3L, 1L);
if(isGetLock) {
try {
int a = counter[0];
counter[0] = a + 1;
logger.info(a + "");
} finally {
redissonDistributedLocker.unlock("test0001");
}
}
}
}).start(); } // 主线程休眠,等待结果
Thread.sleep(5000);
System.out.println(counter[0]);
logger.info(counter[0] + "");
}
闲话就不多说了,希望能对你有所帮助。