分布式锁的实现工具类

分布式锁一般使用缓存实现的,下面提供一个工具类,

1、缓存配置:

bootstrap.yml 或者 application.properties:

spring.redis.cluster.nodes: " x.x.x.x:6379, 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;
		
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值