分布式锁的实现方式 - 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)

相关推荐
敖云岚34 分钟前
【Redis】分布式锁的介绍与演进之路
数据库·redis·分布式
正在努力Coding1 小时前
kafka(windows)
分布式·kafka
让我上个超影吧3 小时前
黑马点评【基于redis实现共享session登录】
java·redis
懒羊羊大王呀6 小时前
Ubuntu20.04中 Redis 的安装和配置
linux·redis
禺垣7 小时前
区块链技术概述
大数据·人工智能·分布式·物联网·去中心化·区块链
John Song8 小时前
Redis 集群批量删除key报错 CROSSSLOT Keys in request don‘t hash to the same slot
数据库·redis·哈希算法
zhuhit10 小时前
FASTDDS的安全设计
分布式·机器人·嵌入式
暗影八度10 小时前
Spark流水线+Gravitino+Marquez数据血缘采集
大数据·分布式·spark
q5673152311 小时前
IBM官网新闻爬虫代码示例
开发语言·分布式·爬虫
不爱学英文的码字机器11 小时前
数据网格的革命:从集中式到分布式的数据管理新范式
分布式