Redis实现分布式锁

在分布式系统中,分布式锁是一个重要的概念,用于协调不同节点间的资源访问。本文将详细介绍如何使用Redis实现分布式锁,并探讨其在Spring Cloud中的应用,包括基本实现和使用Redisson库的高级实现。

  1. Redis实现分布式锁的核心原理

Redis实现分布式锁的核心原理基于其单线程特性和原子操作。主要步骤包括:

a) 获取锁
使用Redis的SET命令来获取锁:

SET key value [EX seconds] [PX milliseconds] [NX|XX]

关键参数解释:

  • key: 锁的名称
  • value: 通常是随机生成的字符串,用于标识锁的持有者
  • NX: 只在键不存在时才设置成功
  • PX milliseconds: 设置键的过期时间(毫秒)

示例命令:

SET lockKey uniqueId NX PX 10000

b) 设置过期时间
在SET命令中通过PX参数设置过期时间,防止死锁。

c) 释放锁
使用Lua脚本确保原子性操作:

if redis.call('get', KEYS[1]) == ARGV[1] then 
    return redis.call('del', KEYS[1]) 
else 
    return 0 
end
  1. Spring Cloud中的基本实现

在Spring Cloud中,我们可以通过以下步骤实现基本的分布式锁:

a) 添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

b) 配置Redis
在application.yml中配置Redis连接信息。

c) 创建Redis配置类

@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, String> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new StringRedisSerializer());
        return template;
    }
}

d) 实现分布式锁服务

@Service
public class DistributedLockService {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    private static final long LOCK_TIMEOUT = 10000; // 10 seconds

    public boolean acquireLock(String lockKey, String requestId) {
        String result = redisTemplate.execute((RedisCallback<String>) connection -> {
            JedisCommands commands = (JedisCommands) connection.getNativeConnection();
            return commands.set(lockKey, requestId, "NX", "PX", LOCK_TIMEOUT);
        });
        return "OK".equals(result);
    }

    public boolean releaseLock(String lockKey, 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((RedisCallback<Long>) connection -> {
            JedisCommands commands = (JedisCommands) connection.getNativeConnection();
            return (Long) commands.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
        });
        return result != null && result > 0;
    }
}
  1. 使用Redisson实现高级分布式锁

Redisson是一个高级Redis客户端,提供了更强大和便捷的分布式锁实现:

a) 添加依赖

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>3.17.0</version>
</dependency>

b) 配置Redisson

@Configuration
public class RedissonConfig {
    @Bean
    public RedissonClient redissonClient() {
        Config config = new Config();
        config.useSingleServer().setAddress("redis://localhost:6379");
        return Redisson.create(config);
    }
}

c) 实现分布式锁服务

@Service
public class DistributedLockService {
    private final RedissonClient redissonClient;

    @Autowired
    public DistributedLockService(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }

    public boolean acquireLock(String lockKey, long waitTime, long leaseTime) {
        RLock lock = redissonClient.getLock(lockKey);
        try {
            return lock.tryLock(waitTime, leaseTime, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return false;
        }
    }

    public void releaseLock(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        if (lock.isHeldByCurrentThread()) {
            lock.unlock();
        }
    }
}
  1. Redisson实现的优势
  • 可重入锁: 同一线程可多次获取同一把锁
  • 自动续期: 自动延长锁的有效期
  • 等待获取锁: 可指定等待时间
  • 看门狗机制: 后台自动延长锁的有效期
  • 公平锁选项: 可实现公平锁
  1. 在业务中使用分布式锁
@Service
public class BusinessService {
    private final DistributedLockService lockService;

    @Autowired
    public BusinessService(DistributedLockService lockService) {
        this.lockService = lockService;
    }

    public void performBusinessOperation() {
        String lockKey = "business_operation_lock";
        boolean locked = false;

        try {
            locked = lockService.acquireLock(lockKey, 5000, 10000);
            if (locked) {
                // 执行需要加锁的业务逻辑
                System.out.println("执行业务操作...");
                Thread.sleep(5000);
            } else {
                System.out.println("获取锁失败,请稍后重试");
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            System.out.println("业务操作被中断");
        } finally {
            if (locked) {
                lockService.releaseLock(lockKey);
            }
        }
    }
}

Redis实现的分布式锁为Spring Cloud微服务提供了一种有效的资源协调机制。从基本的SET命令实现到使用Redisson的高级特性,开发者可以根据具体需求选择合适的实现方式。在实际应用中,需要考虑锁的可靠性、性能影响以及潜在的问题(如网络分区)。合理使用分布式锁可以显著提高分布式系统的数据一致性和操作原子性。

posted on 2024-06-29 15:31  滚动的蛋  阅读(30)  评论(0编辑  收藏  举报

导航