用一个 Redis 实现分布式锁.
1. 为什么要用 reids 实现分布式锁 (比较于 syschronized 的优势) : 既然是分布式锁于 syschronized 的优势 就在于分布式可用. java 提供的 syschronized,lock(syschronized,lock 内存语义不同. 以后会写) 等但是只适用于一个服务器.
www.Redis.cn 中文 Redis 网站.
本次实现 Redis 分布式锁的几个 Redis 命令.
SETNX : 将 key 设置值为 value, 如果 key 不存在, 这种情况下等同 SET 命令. 当 key 存在时, 什么也不做. SETNX 是 "SETifNot eXists" 的简写
GETSET: 自动将 key 对应到 value 并且返回原来 key 对应的 value. 如果 key 存在但是对应的 value 不是字符串, 就返回错误.
代码:
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.data.Redis.core.StringRedisTemplate;
- import org.springframework.stereotype.Component;
- import org.springframework.util.StringUtils;
- @Component
- @Slf4j
- public class RedisLock {
- @Autowired
- private StringRedisTemplate redisTemplate;
- /**
- * @param key 订单 id
- * @param value 当前时间 + 超时时间
- * @return
- */
- public synchronized boolean lock(String key,String value){
- // 对应的是 reids 中的 SETNX 命令 设置成功为 true
- if(redisTemplate.opsForValue().setIfAbsent(key, value)){
- return true;
- }
- // 下面的意义是解决 当我们加锁后由于代码或者网络的原因中间抛出异常未能正常解锁
- String currentValue = redisTemplate.opsForValue().get(key);
- if(!StringUtils.isEmpty(currentValue) && Long.parseLong(currentValue)<System.currentTimeMillis()){
- // 获取上一个锁的时间
- String oldValue = redisTemplate.opsForValue().getAndSet(key, value);
- if(oldValue != null && oldValue.equals(currentValue)){
- return true;
- }
- }
- return false;
- }
- /**
- * 解锁
- * @param key
- * @param value
- */
- public void unlock(String key, String value){
- try {
- String currentValue = redisTemplate.opsForValue().get(key);
- if(!StringUtils.isEmpty(currentValue) && currentValue.equals(value)){
- redisTemplate.opsForValue().getOperations().delete(key);
- }
- }catch (Exception e){
- log.error("[redis 分布式锁解锁异常] ,{}",e );
- }
- }
- }
我用的是 springBoot 2.0.5 版本的
- <!--redis 依赖 -->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-Redis</artifactId>
- </dependency>
- <!--@Slf4j 依赖 -->
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- </dependency>
- GETSET
来源: http://www.bubuko.com/infodetail-2872253.html