java结合redistemplate使用分布式锁案例

在Java中使用RedisTemplate结合Redis来实现分布式锁是一种常见的做法,特别适用于微服务架构或多实例部署的应用程序中,以确保数据的一致性和避免竞态条件。以下是一个简单的使用Spring Boot和RedisTemplate实现分布式锁的案例。

1. 引入依赖

首先,确保你的Spring Boot项目中已经包含了Redis相关的依赖。如果是Maven项目,可以在pom.xml中添加如下依赖:

复制代码
<dependency>  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-data-redis</artifactId>  
</dependency>

2. 配置Redis

application.propertiesapplication.yml中配置Redis服务器的连接信息:

复制代码
# application.properties 示例  
spring.redis.host=localhost  
spring.redis.port=6379  
spring.redis.password= # 如果Redis设置了密码,请填写

3. 实现分布式锁

使用Redis实现分布式锁的关键在于利用Redis的原子操作(如SETNXSET命令的NXPX选项)来确保锁的互斥性。在Spring Boot中,我们可以通过自定义服务或使用RedisTemplate直接操作Redis。

下面是一个简单的分布式锁实现:

复制代码
import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.data.redis.core.RedisTemplate;  
import org.springframework.data.redis.core.script.DefaultRedisScript;  
import org.springframework.stereotype.Service;  
  
import java.util.Collections;  
import java.util.UUID;  
import java.util.concurrent.TimeUnit;  
  
@Service  
public class RedisLockService {  
  
    @Autowired  
    private RedisTemplate<String, Object> redisTemplate;  
  
    private static final String LOCK_PREFIX = "lock:";  
  
    /**  
     * 尝试获取锁  
     * @param key 锁的key  
     * @param expireTime 锁的过期时间,单位秒  
     * @return 是否获取锁成功  
     */  
    public boolean tryLock(String key, long expireTime) {  
        String requestId = UUID.randomUUID().toString();  
        String result = redisTemplate.opsForValue().setIfAbsent(LOCK_PREFIX + key, requestId, expireTime, TimeUnit.SECONDS);  
        return "OK".equals(result);  
    }  
  
    /**  
     * 释放锁  
     * @param key 锁的key  
     * @param requestId 请求的唯一标识  
     * @return 是否释放锁成功  
     */  
    public boolean releaseLock(String key, String requestId) {  
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";  
        Long result = redisTemplate.execute(new DefaultRedisScript<>(script, Long.class), Collections.singletonList(LOCK_PREFIX + key), requestId);  
        return result != null && result > 0;  
    }  
}

4. 使用分布式锁

在你的业务逻辑中,可以这样使用RedisLockService

复制代码
@Autowired  
private RedisLockService redisLockService;  
  
public void criticalSection() {  
    String lockKey = "yourLockKey";  
    try {  
        if (redisLockService.tryLock(lockKey, 10)) { // 尝试获取锁,10秒过期  
            // 执行你的关键代码  
            // ...  
        }  
    } finally {  
        redisLockService.releaseLock(lockKey, requestId); // 释放锁,requestId需要是之前尝试加锁时生成的UUID  
    }  
}

注意:这里的requestId需要是在尝试加锁时生成的,并在释放锁时使用相同的值。实际使用中,你可能需要在调用tryLock方法之前或方法中生成requestId,并在调用releaseLock时传递它。

5. 注意事项

  • 确保锁的粒度适中,避免过细或过粗的锁导致性能问题或并发限制。
  • 考虑锁的续期问题,特别是在长时间运行的操作中。
  • 在分布式系统中,锁失败是常态,确保你的代码能够妥善处理锁失败的情况。
相关推荐
angushine20 分钟前
Gateway获取下游最终响应码
java·开发语言·gateway
爱的叹息26 分钟前
关于 JDK 中的 jce.jar 的详解,以及与之功能类似的主流加解密工具的详细对比分析
java·python·jar
一一Null33 分钟前
Token安全存储的几种方式
android·java·安全·android studio
西贝爱学习38 分钟前
数据结构:C语言版严蔚敏和解析介绍,附pdf
c语言·开发语言·数据结构
AUGENSTERN_dc40 分钟前
RaabitMQ 快速入门
java·后端·rabbitmq
程丞Q香41 分钟前
python——学生管理系统
开发语言·python·pycharm
晓纪同学1 小时前
C++ Primer (第五版)-第十三章 拷贝控制
java·开发语言·c++
小样vvv1 小时前
【源码】SpringMvc源码分析
java
nzwen6661 小时前
Redis学习笔记及总结
java·redis·学习笔记