package com.example.demo.dao.redis; import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import javax.annotation.Resource; @Slf4j @Component public class RedisLock { @Resource private StringRedisTemplate redisTemplate; /** * 加锁 * * @param value 当前时间+超时时间 * @return 是否拿到锁 */ public boolean lock(String key, String value) { //setnx命令 if (Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(key, value))) { 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不一样了 return currentValue.equals(oldValues); } return false; } /** * 解锁 */ 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); } } }