Skip to content

SpringRedis分布式锁

依赖

java
 <!--spring-redis分布式锁-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-integration</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.integration</groupId>
            <artifactId>spring-integration-redis</artifactId>
            <version>5.0.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

配置

java
spring:
  redis:
    host: 192.168.0.202
    port: 6379

工具类

DistributionLockConfiguration

java
/**
 * 分布式锁配置
 *
 * @author gavin
 * @date 2020-06-18
 */
@Configuration
public class DistributionLockConfiguration {

    private static final String DEFALULT_LOCK_KEY = "DEFALULT_DISTRIBUTION_LOCK";

    /**
     * 初始化redis分布式锁配置.
     *
     * 注意,这里的分布式锁的解锁时间默认为60秒,这可能会导致以下安全性问题(出现概率依次递减):
     * 1. 分布式锁用在网络IO的场景,必须设置超时时间,否则可能会因为对方超时导致锁自动释放(奇门的超时时间不能高于分布式锁的加锁时间)
     * 2. 服务器时钟跳跃,可能会出现不可预料的锁到期情况,可能出现的场景:业务因其他原因执行时间过长 + 服务器时钟跳跃 可能会导致分布式锁自动释放
     * 3. JVM GC的STW过长导致(OMS中几乎不可能出现STW长达60秒的情况)
     *
     * @param connectionFactory redis连接工厂
     * @return redis分布式锁配置
     */
    @Bean
    public RedisLockRegistry defaultRedisLockRegistry(RedisConnectionFactory connectionFactory) {
        return new RedisLockRegistry(connectionFactory, DEFALULT_LOCK_KEY);
    }

    @Bean
    public DistributionLock defaultDistributionLock(RedisLockRegistry redisLockRegistry) {
        return new SpringRedisLock(redisLockRegistry);
    }
}

DistributionLock

java
/**
 * @author gavin
 * @date 2020-06-18
 */
public interface DistributionLock {

    void lock(String var1);

    boolean tryLock(String var1, long var2, TimeUnit var4);

    void unlock(String var1);
}

SpringRedisLock

java
/**
 * @author gavin
 * @date 2020-06-18
 */
public class SpringRedisLock implements DistributionLock {

    private static final Logger LOGGER = LoggerFactory.getLogger(SpringRedisLock.class);
    private RedisLockRegistry redisLockRegistry;

    public SpringRedisLock(RedisLockRegistry redisLockRegistry) {
        this.redisLockRegistry = redisLockRegistry;
    }

    @Override
    public void lock(String key) {
        this.redisLockRegistry.obtain(key).lock();
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug(String.format("线程%s获取锁成功", Thread.currentThread().getName()));
        }

    }

    @Override
    public boolean tryLock(String key, long waitTimeout, TimeUnit timeUnit) {
        Lock lock = this.redisLockRegistry.obtain(key);

        try {
            boolean isLockSuccess = lock.tryLock(waitTimeout, timeUnit);
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug(String.format("线程%s获取锁%s", Thread.currentThread().getName(), isLockSuccess ? "成功" : "失败"));
            }

            return isLockSuccess;
        } catch (InterruptedException var7) {
            return false;
        }
    }

    @Override
    public void unlock(String key) {
        this.redisLockRegistry.obtain(key).unlock();
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug(String.format("线程%s释放锁", Thread.currentThread().getName()));
        }

    }
}

DistributionLockUtil

java
/**
 * 构建分布式锁的工具类
 *
 * @author gavin
 * @date 2020-06-18
 */
public class DistributionLockUtil {

    private static final String DISTRIBUTION_LOCK = "DISTRIBUTION_LOCK_";

    /**
     * 构建分布式锁的key
     *
     * @param bizCode 业务编码
     * @return key
     */
    public static String buildKey(String bizCode) {
        return DISTRIBUTION_LOCK + bizCode;
    }
}