分布式锁的实现方式 - redis

场景:项目要从单实例变为多实例部署了,从而引入了一个问题,就是定时任务会多次执行(没一个实例都会执行一次)。为了解决这个问题,就要使用到分布式锁。

使用哪一种方式实现分布式锁

分布式锁的实现有多种:

  • 第一种:使用数据库,当要上锁时想数据库中添加一条数据,释放锁时删除数据即可。这种方式要维护一张存放锁状态的表。而且性能不好,不推荐使用。
  • 第二种:使用 zookeeper 来实现,zookeeper 是分布式协调服务,它的数据是以节点的方式存储,节点操作是原子性的。当我们要上锁时,添加一个临时节点,释放锁时删除这个节点。
  • 第三种:使用 redis 来实现。redis 中的 SETNX 命令是原子性的,命令可以尝试将一个指定的键设置为某个值,只有当该键不存在时才能设置成功。

因为我在项目中没有使用到 zookeeper ,所以不用为了实现分布式锁而去部署一套 zookeeper。 而数据库方式有性能问题,最终选择了使用 redis 方式实现。

创建 RedisDistributedLock 工具类

SpringBoot项目使用的 redisTemplate 来操作 redis,具体代码如下:

java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;

@Component
public class RedisDistributedLock {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    public boolean lock(String lockKey, String lockValue, long expireTime) {
        return redisTemplate.opsForValue().setIfAbsent(lockKey, lockValue,expireTime, TimeUnit.MILLISECONDS);
    }


    public void unLock(String lockKey, String lockValue) {
        String currentValue = redisTemplate.opsForValue().get(lockKey);
        if (currentValue != null && currentValue.equals(lockValue)) {
            String luaScript = "if redis.call('get', KEYS[1]) then return redis.call('del', KEYS[1]) else return 0 end";
            RedisScript<Long> redisScript = new DefaultRedisScript<>(luaScript, Long.class);
            redisTemplate.execute(redisScript, Collections.singletonList(lockKey));
        }
    }
}

lock 方法中的 lockKey 为锁的对象,lockValue 是为释放锁时会用到,防止释放了别人的锁,expireTime 是为了防止死锁。

unlock 方法中使用了 lua 脚本,确保正确的释放锁。

END

PS:欢迎大家关注我的公众号 小城边AI,直接搜索即可添加,可以体验AI问答,持续为大家推送相关优质技术文,共同进步,一起加油~

个人导航网站:小城边-个人导航 (gitee.io)

相关推荐
翰林小院2 小时前
【RabbitMQ】 RabbitMQ Overview
分布式·rabbitmq
xujiangyan_2 小时前
Redis详解
数据库·redis·缓存
失散137 小时前
分布式专题——39 RocketMQ客户端编程模型
java·分布式·架构·rocketmq
泽02028 小时前
Linux之环境变量
java·linux·redis
济南java开发,求内推8 小时前
Redis一个服务器部署多个节点
服务器·数据库·redis
Full Stack Developme8 小时前
Python Redis 教程
开发语言·redis·python
一个尚在学习的计算机小白8 小时前
RabbitMQ
分布式·rabbitmq
奥尔特星云大使9 小时前
MySQL分布式架构:MyCat详解
数据库·分布式·mysql·mycat·高可用
夜泉_ly10 小时前
Redis -持久化
数据库·redis·缓存
用户311879455921811 小时前
redis-4.0.11-1.ky10.sw_64.rpm安装教程(申威麒麟V10 64位系统详细步骤)
redis