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. 注意事项

  • 确保锁的粒度适中,避免过细或过粗的锁导致性能问题或并发限制。
  • 考虑锁的续期问题,特别是在长时间运行的操作中。
  • 在分布式系统中,锁失败是常态,确保你的代码能够妥善处理锁失败的情况。
相关推荐
奶香臭豆腐2 分钟前
C++ —— 模板类具体化
开发语言·c++·学习
晚夜微雨问海棠呀10 分钟前
长沙景区数据分析项目实现
开发语言·python·信息可视化
graceyun10 分钟前
C语言初阶习题【9】数9的个数
c语言·开发语言
hanbarger12 分钟前
mybatis框架——缓存,分页
java·spring·mybatis
cdut_suye20 分钟前
Linux工具使用指南:从apt管理、gcc编译到makefile构建与gdb调试
java·linux·运维·服务器·c++·人工智能·python
技术路上的苦行僧24 分钟前
分布式专题(10)之ShardingSphere分库分表实战指南
分布式·shardingsphere·分库分表
苹果醋332 分钟前
2020重新出发,MySql基础,MySql表数据操作
java·运维·spring boot·mysql·nginx
小蜗牛慢慢爬行33 分钟前
如何在 Spring Boot 微服务中设置和管理多个数据库
java·数据库·spring boot·后端·微服务·架构·hibernate
azhou的代码园36 分钟前
基于JAVA+SpringBoot+Vue的制造装备物联及生产管理ERP系统
java·spring boot·制造
hanbarger37 分钟前
nosql,Redis,minio,elasticsearch
数据库·redis·nosql