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

  • 确保锁的粒度适中,避免过细或过粗的锁导致性能问题或并发限制。
  • 考虑锁的续期问题,特别是在长时间运行的操作中。
  • 在分布式系统中,锁失败是常态,确保你的代码能够妥善处理锁失败的情况。
相关推荐
kyle~2 分钟前
C/C++---动态内存管理(new delete)
c语言·开发语言·c++
沃夫上校10 分钟前
MySQL 中文拼音排序问题
java·mysql
Dcs14 分钟前
用 Python UTCP 直调 HTTP、CLI、MCP……
java
无名客022 分钟前
redis分布式锁为什么采用Lua脚本实现。而不是事务
redis·分布式·lua·事务
落日沉溺于海38 分钟前
React From表单使用Formik和yup进行校验
开发语言·前端·javascript
快乐肚皮1 小时前
fencing token机制
java·fencing token
梦中的天之酒壶1 小时前
Redis Stack扩展功能
数据库·redis·bootstrap
叶落阁主1 小时前
Neovim 插件 i18n.nvim 介绍
java·vue.js·vim
渣哥1 小时前
让集合线程安全的几种靠谱方法
java
dylan_QAQ1 小时前
Java转Go全过程06-工程管理
java·后端·go