springboot2结合redis,实现分布式锁

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 jsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        jsonRedisSerializer.setObjectMapper(objectMapper);
        redisTemplate.setDefaultSerializer(jsonRedisSerializer);

        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
}
 
  

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分支

你可能感兴趣的:(javaweb)