简洁实用的Redis分布式锁用法
Redis分布式锁原理概述
首先Redis客户端获取当前系统时间,以毫秒为单位; 然后客户端会顺序地尝试向Redis集群中的每个节点获取锁,其具体步骤是使用相同的键Key名和随机值;在向每个Redis节点获取锁的过程中,客户端会以比锁过期时间小得多的时间来设定超时机制,例如锁的整个超时时间为10秒,集群有5个节点,那么每个节点获取锁的超时时间可能会被限制在5~50毫秒之间,这是为了防止在某个节点不可用的情况下,客户端等待时间过长,造成性能阻塞; 之后随着各节点获取锁结果的反馈,Redis客户端会对获取情况进行判断,如果获取各节点锁的总时间小于锁的超时时间设置,并且成功获取锁的节点数目大于N/2+1个(例如5个节点至少要有3个节点成功获取锁),满足上述条件的情况下,Redis客户端才会认为获取锁成功,否则就会认为锁获取失败,并依次释放掉各个节点的锁信息; 获取锁成功后即可以安全地执行操作,完成后再依次释放各节点锁持有的锁信息;
互斥:任何时刻只能有一个Redis客户端获取锁; 无死锁:即使锁定资源的服务崩溃或者分区,仍然能释放锁); 容错性:只要多数redis节点(一半以上)在使用,Redis客户端就可以获取和释放锁;
Spring Boot集成使用方式
1)在工程pom.xml文件中引入Spring Integration依赖,代码如下:
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-integrationartifactId>
dependency>
<dependency>
<groupId>org.springframework.integrationgroupId>
<artifactId>spring-integration-redisartifactId>
dependency>
目前Spring所提供的分布式锁相关的代码被迁移在Spring Integration子项目中,所以这里引入其相关依赖。
2)编写RedisLock的配置类,代码如下:
@Configuration
public class RedisLockConfiguration {
@Bean
public RedisLockRegistry redisLockRegistry(RedisConnectionFactory redisConnectionFactory) {
return new RedisLockRegistry(redisConnectionFactory, "payment");
}
}
以上配置代码加载的前提在于应用已经集成了Redis服务访问链接信息,具体Spring Boot项目集成Redis访问的方式比较简单可以参考其他资料。
3)分布式锁的具体使用方式,代码片段如下:
/**
* 引入Redis分布式锁依赖组件
*/
@Autowired
private RedisLockRegistry redisLockRegistry;
@Override
public UnifiedPayBO unifiedPay(UnifiedPayDTO unifiedPayDTO) {
...
//创建Redis分布式锁
Lock lock = redisLockRegistry.obtain(redisLockPrefix + unifiedPayDTO.getOrderId());
try {
//尝试获取锁
boolean isLock = lock.tryLock(1, TimeUnit.SECONDS);
if (isLock) {
//执行业务逻辑
...
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//释放分布式锁
lock.unlock();
}
...
}
上述代码为订单防重时使用Redis分布锁的示例代码,通过依赖注入RedisLockRegistry实例来实现分布式锁的相关操作,例如obtain()方法创建锁、tryLock()持有锁及unlock()释放锁等。
—————END—————
推荐阅读:
实战:一键生成前后端代码,Mybatis-Plus代码生成器让我舒服了
为什么要重写 hashcode 和 equals 方法?
SpringBoot @Value 解析集合配置
推荐阅读:
评论