redis 實現分佈式鎖(二)

1、依賴包

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <version>2.1.3.RELEASE</version>
        </dependency>

 

2、分佈式鎖


import com.zto.ztrace.util.RedisStringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

@Component
public class RedisLock {
	/**
	 * redis操作的類
	 */
	@Autowired
	private RedisStringUtil redisStringUtil;

	/**
	 * 加鎖的值
	 */
	private static final String LOCK_VALUE = "TRUE";

	/**
	 * 默認超時時間 3000ms
	 */
	private static final int TIME = 3000;

	/**
	 * 鎖的前綴,命名空間
	 */
	private static final String PREFIX = "LOCKS:";

	/**
	 * 加鎖
	 *
	 * @param key 鍵
	 * @return 返回是否允許執行
	 */
	public boolean lock(final String key) {
		return this.redisStringUtil.setIfNotExists(RedisLock.PREFIX.concat(key), RedisLock.LOCK_VALUE, RedisLock.TIME);
	}

	/**
	 * 加鎖,有超時時間(建議) 避免解鎖失敗導致死鎖
	 *
	 * @param key                鍵
	 * @param expireMilliSeconds 超時時間(默認 耗秒)
	 * @return 返回是否允許執行
	 */
	public boolean lock(final String key, final long expireMilliSeconds) {
		return this.redisStringUtil.setIfNotExists(RedisLock.PREFIX.concat(key), RedisLock.LOCK_VALUE, expireMilliSeconds);
	}

	/**
	 * 加鎖,有超時時間(建議) 避免解鎖失敗導致死鎖
	 *
	 * @param key  鍵
	 * @param time 超時時間
	 * @param unit 超時單位
	 * @return 返回是否允許執行
	 */
	public boolean lock(final String key, final long time, final TimeUnit unit) {
		return this.redisStringUtil.setIfNotExists(RedisLock.PREFIX.concat(key), RedisLock.LOCK_VALUE, time, unit);
	}

	/**
	 * 解鎖  this.redisStringUtil.set(PREFIX.concat(key), LOCK_VALUE, 5, TimeUnit.MILLISECONDS);
	 *
	 * @param key 鍵
	 */
	public void unlock(final String key) {
		this.redisStringUtil.delete(RedisLock.PREFIX.concat(key));
	}
}

 

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

@Component
public class RedisStringUtil {

	/**
	 * 注入Redis字符串模板
	 */
	@Autowired
	private StringRedisTemplate redisTemplate;

	/**
	 * 設置值
	 *
	 * @param key   鍵
	 * @param value 值
	 */
	public void set(final String key, final String value) {
		this.redisTemplate.opsForValue().set(key, value);
	}

	/**
	 * 當前的值 + 1
	 *
	 * @param key 鍵
	 * @return 返回操作之後的值
	 */
	public Long increment(final String key) {
		return this.redisTemplate.opsForValue().increment(key, 1);
	}

	/**
	 * 當前的值加 + value
	 *
	 * @param key   鍵
	 * @param value 值
	 * @return 返回操作之後的值
	 */
	public Long incrementBy(final String key, final long value) {
		return this.redisTemplate.opsForValue().increment(key, value);
	}

	/**
	 * 當前的值 - 1
	 *
	 * @param key 鍵
	 * @return 返回操作之後的值
	 */
	public Long descend(final String key) {
		return this.redisTemplate.opsForValue().increment(key, -1);
	}

	/**
	 * 當前的值 - value
	 *
	 * @param key 鍵
	 * @return 返回操作之後的值
	 */
	public Long descendBy(final String key, final long value) {
		return this.redisTemplate.opsForValue().increment(key, -Math.abs(value));
	}

	/**
	 * 設置值
	 *
	 * @param key     鍵
	 * @param value   值
	 * @param timeout 超時(秒)
	 */
	public void set(final String key, final String value, final long timeout) {
		this.redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
	}

	/**
	 * 設置值
	 *
	 * @param key     鍵
	 * @param value   值
	 * @param timeout 超時時間
	 * @param timeout 超時時間單位
	 */
	public void set(final String key, final String value, final long timeout, final TimeUnit timeUnit) {
		this.redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
	}

	/**
	 * 獲取值
	 *
	 * @param key 鍵
	 * @return 獲取值
	 */
	public String get(final String key) {
		return this.redisTemplate.opsForValue().get(key);
	}

	/**
	 * 刪除
	 *
	 * @param key 健
	 */
	public void delete(final String key) {
		this.redisTemplate.delete(key);
	}

	/**
	 * 當不存在的時候設置值,
	 *
	 * @param key                鍵
	 * @param value              值
	 * @param expireMilliSeconds 超時時間(單位 毫秒)
	 * @return 成功 返回 OK
	 */
	public boolean setIfNotExists(final String key, final String value, final long expireMilliSeconds) {
		return this.setIfNotExists(key, value, expireMilliSeconds, TimeUnit.MILLISECONDS);
	}

	/**
	 * 當不存在的時候設置值,
	 *
	 * @param key      鍵
	 * @param value    值
	 * @param expire   超時時間
	 * @param timeUnit 超時單位
	 * @return 成功 返回 OK
	 */
	public boolean setIfNotExists(final String key, final String value, final long expire, final TimeUnit timeUnit) {
		return this.redisTemplate.opsForValue().setIfAbsent(key, value, expire, timeUnit);
	}
}

 

3 、使用方式

import com.zto.ztrace.extend.RedisLock;
 
 
@Autowired
private RedisLock redisLock;
 
if (this.redisLock.lock(key)) {
    try {
      // 業務邏輯
    } finally {
        this.redisLock.unlock(key);
    }
}else{
 // 獲取鎖失敗
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章