分布式锁的实现工具类
Posted 格子衫111
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分布式锁的实现工具类相关的知识,希望对你有一定的参考价值。
分布式锁一般使用缓存实现的,下面提供一个工具类,
1、缓存配置:
bootstrap.yml 或者 application.properties:
spring.redis.cluster.nodes: x.x.x.x:6379
spring.cache.redis.timeToLive: 360
2、添加pom依赖:
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.17</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
<!-- 引入redisTemplate-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.7.0</version>
</dependency>
3、辅助工具类:
ErrorInfoEnum.java
/**
* 系统及业务级别的通用错误码
*/
public enum ErrorInfoEnum
//成功
SUCCESS("0", "success"),
ORDER_RESERVATION_GET_LOCK_ERROR("-110","加锁失败"),
//失败
FAILED("-1", "system exception");
private String code;
private String message;
ErrorInfoEnum(String code, String message)
this.code = code;
this.message = message;
public String getCode()
return code;
public void setCode(String code)
this.code = code;
public String getMessage()
return message;
public void setMessage(String message)
this.message = message;
@Override
public String toString()
return "ErrorInfoEnum" +
"code='" + code + '\\'' +
", message='" + message + '\\'' +
'';
ReqBody.java
/**
* 请求体
* @param <T>
*/
public final class ReqBody<T>
private static final long serialVersionUID = 1L;
// 调用方应用名称
protected String appName;
// 数据来源
protected String source;
// 加密签名
private String sign;
//时间戳
private String timestamp;
//参数体
protected T param;
public String getAppName()
return appName;
public void setAppName(String appName)
this.appName = appName;
public String getSource()
return source;
public void setSource(String source)
this.source = source;
public String getSign()
return sign;
public void setSign(String sign)
this.sign = sign;
public String getTimestamp()
return timestamp;
public void setTimestamp(String timestamp)
this.timestamp = timestamp;
public T getParam()
return param;
public void setParam(T param)
this.param = param;
@Override
public String toString()
return "ReqBody" +
"appName='" + appName + '\\'' +
", source='" + source + '\\'' +
", sign='" + sign + '\\'' +
", timestamp='" + timestamp + '\\'' +
", param=" + param +
'';
RespBody.java
/**
* 返回体
*/
public final class RespBody<T> implements Serializable
private static final long serialVersionUID = -3455864552409084052L;
/**
* 响应代码
*/
private String code;
/**
* 响应消息
*/
private String message;
/**
* 响应结果
*/
private transient T result;
public RespBody()
successParam();
public RespBody(T result)
successParam();
this.result = result;
public void setIErrorInfo(ErrorInfoEnum errorInfo)
this.code = errorInfo.getCode();
this.message = errorInfo.getMessage();
private void successParam()
this.code = ErrorInfoEnum.SUCCESS.getCode();
this.message = ErrorInfoEnum.SUCCESS.getMessage();
4、缓存工具类:
import com.alibaba.fastjson2.JSONObject;
import com.zwt.common.ReqBody;
import com.zwt.common.RespBody;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
@Service
public class RedisTemplateService
private Logger log = LoggerFactory.getLogger(RedisTemplateService.class);
@Autowired
private RedisTemplate redisTemplate;
public RespBody<String> getRedisObjectByKey(ReqBody<String> reqBody)
String result = null;
if (!StringUtils.isEmpty(reqBody.getParam()))
Object lightObject = redisTemplate.opsForValue().get(reqBody.getParam());
result = JSONObject.toJSONString(lightObject);
return new RespBody<>(result);
public RespBody<String> getRedisListByKey(ReqBody<String> reqBody)
String result = null;
if (!StringUtils.isEmpty(reqBody.getParam()))
Object lightObject = redisTemplate.opsForList().range(reqBody.getParam(), 0, -1);
result = JSONObject.toJSONString(lightObject);
return new RespBody<>(result);
public RespBody<Object> setRedisObjectByKey(ReqBody<List<String>> reqBody)
redisTemplate.opsForValue().set(reqBody.getParam().get(0), reqBody.getParam().get(1),
Integer.parseInt(reqBody.getParam().get(2)), TimeUnit.MINUTES);
return new RespBody<>();
public RespBody<Object> setRedisListByKey(ReqBody<List<String>> reqBody)
Object ob = redisTemplate.opsForList().rightPush(reqBody.getParam().get(0), reqBody.getParam().get(1));
return new RespBody<>(ob);
public RespBody<Object> deleteRedisObjectByKey(ReqBody<String> reqBody)
// 删除redis的值
redisTemplate.opsForValue().set(reqBody.getParam(), 1, 1, TimeUnit.MILLISECONDS);
return new RespBody<>();
public RespBody<Object> deleteRedisListByKey(ReqBody<List<String>> reqBody)
// 删除redis的值
redisTemplate.opsForList().remove(reqBody.getParam().get(0), 0, reqBody.getParam().get(1));
return new RespBody<>();
/**
* 加分布式锁
*
* @param key
* @return
*/
public boolean lock(String key,int seconds)
Boolean result = redisTemplate.opsForValue().setIfAbsent(key, System.currentTimeMillis(), seconds, TimeUnit.SECONDS);
log.info("[] 加分布式锁,过期时间 秒,加锁结果 = ", key, seconds, result);
return result;
/**
* 解锁
* @param key
* @return
*/
public Boolean unlock(String key)
log.info(" 解锁", key);
return redisTemplate.opsForValue().getOperations().delete(key);
3、业务代码中使用分布式锁:
1)引用缓存工具类
@Autowired
private RedisTemplateService redisTemplateService;
2)方法中伪代码
// 加锁,一般1个固定字符串加一个字段(具有唯一性)
String key = REDIS_KEY + reserveId;
boolean lock = redisTemplateService.lock(key, EXPIRETIME_10S);
if (!lock)
log.error("key=加锁失败", key);
throw new GlobalErrorInfoException(ErrorInfoEnum .ORDER_RESERVATION_GET_LOCK_ERROR);
try
// 业务代码
finally
//锁释放
redisTemplateService.unlock(key);
4、涉及的常量:
// 锁的key,根据自身业务自定义
public static final String REDIS_KEY = "MT:RESERVE:";
// 锁过期时间,根据方法逻辑处理复杂度自定义
public static final Integer EXPIRETIME_10S = 10;
以上是关于分布式锁的实现工具类的主要内容,如果未能解决你的问题,请参考以下文章