1.添加Maven依赖
org.apache.commons
commons-pool2
2.5.0
redis.clients
jedis
org.springframework.boot
spring-boot-starter-data-redis
io.lettuce
lettuce-core
org.springframework.boot
spring-boot-starter-test
test
2.application.properties配置
spring.redis.host=182.92.234.232
spring.redis.port=6379
spring.redis.password=
spring.redis.timeout=2000
3.自定义RedisConfig
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.password}")
private String password;
@Value("${spring.redis.timeout}")
private int timeout;
@Bean
public JedisPool redisPoolFactory() {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
if (StringUtils.isEmpty(password)) {
return new JedisPool(jedisPoolConfig, host, port, timeout);
}
return new JedisPool(jedisPoolConfig, host, port, timeout, password);
}
@Bean(name = "redisTemplate")
public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, Visibility.ANY);
objectMapper.enableDefaultTyping(DefaultTyping.NON_FINAL);
Jackson2JsonRedisSerializer
4.自定义RedisLockUtils
public class RedisLockUtils {
private static final String SET_IF_NOT_EXIST = "NX";
private static final String SET_WITH_EXPIRE_TIME = "PX";
private static final String LOCK_SUCCESS = "OK";
private static final Long RELEASE_SUCCESS = 1L;
/**
* @param expireTime ms
*/
public static boolean tryLock(Jedis jedis, String lockName, String resourcePath, int expireTime) {
String result = jedis.set(lockName, resourcePath, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
if (LOCK_SUCCESS.equals(result)) {
return true;
}
return false;
}
public static boolean release(Jedis jedis, String lockName, String resourcePath) {
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
Object result = jedis.eval(script, Collections.singletonList(lockName), Collections.singletonList(resourcePath));
if (RELEASE_SUCCESS.equals(result)) {
return true;
}
return false;
}
}
4.测试用例
@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {
@Autowired
private JedisPool jedisPool;
private static final String LOCK_NAME = "LOCK_ID";
private static final String PATH = "TEST_UUID/TEST";
@Test
public void testLock01() {
Jedis jedis = jedisPool.getResource();
boolean lockStatus = RedisLockUtils.tryLock(jedis, LOCK_NAME, PATH, 100000);
if (lockStatus) {
System.out.println("拿到锁了");
// debugger
RedisLockUtils.release(jedis, LOCK_NAME, PATH);
} else {
System.out.println("没有拿到锁");
}
}
@Test
public void testLock02() {
Jedis jedis = jedisPool.getResource();
boolean lockStatus = RedisLockUtils.tryLock(jedis, LOCK_NAME, PATH, 5000);
if (lockStatus) {
System.out.println("拿到锁了");
RedisLockUtils.release(jedis, LOCK_NAME, PATH);
} else {
System.out.println("没有拿到锁");
}
}
}
debugger处打个断点 先debug运行testLock01; 然后运行testLock02, 发现testLock01可以拿到锁, 而testLock02拿不到锁!
源码 https://gitee.com/jsjack_wang/springboot-demo dev-redis-lock分支