分布式锁-redis
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import java.util.concurrent.TimeUnit; /** * */ @Component public class RedisLock { Logger logger = LoggerFactory.getLogger(this.getClass()); @Autowired private StringRedisTemplate redisTemplate; /** * 加锁 * @param key * @param currentTimeMillis 当前时间 * @param timeoutMillis 超时时间 * @return */ public boolean lock(String key,long currentTimeMillis, long timeoutMillis) { String value= String.valueOf(currentTimeMillis+timeoutMillis); //这个其实就是setnx命令,只不过在java这边稍有变化,返回的是boolea if (redisTemplate.opsForValue().setIfAbsent(key, value)) { //这个过期不是原子操作,只是正常为了设置 redisTemplate.expire(key,timeoutMillis, TimeUnit.MILLISECONDS); return true; } //避免死锁,且只让一个线程拿到锁 String currentValue = redisTemplate.opsForValue().get(key); //如果锁过期了 if (!StringUtils.isEmpty(currentValue) && Long.parseLong(currentValue) < System.currentTimeMillis()) { //获取上一个锁的时间 String oldValues = redisTemplate.opsForValue().getAndSet(key, value); /* 只会让一个线程拿到锁 如果旧的value和currentValue相等,只会有一个线程达成条件,因为第二个线程拿到的oldValue已经和currentValue不一样了 */ if (!StringUtils.isEmpty(oldValues) && oldValues.equals(currentValue)) { return true; } } return false; } /** * 解锁 * @param key */ public void unlock(String key, long currentTimeMillis, long timeoutMillis) { String value= String.valueOf(currentTimeMillis+timeoutMillis); try { String currentValue = redisTemplate.opsForValue().get(key); if (!StringUtils.isEmpty(currentValue) && currentValue.equals(value)) { redisTemplate.opsForValue().getOperations().delete(key); } } catch (Exception e) { logger.error("『redis分布式锁』解锁异常,{}", e); } } }
使用