`

使用SETNX实现分布式锁

阅读更多
A: SETNX key value

将 key 的值设为 value,当且仅当 key 不存在。
若给定的 key 已经存在,则 SETNX 不做任何动作。
SETNX 是SET if Not eXists的简写。

返回值
返回整数,具体为
- 1,当 key 的值被设置
- 0,当 key 的值没被设置

(1)setnx lock1 1
第一次设置lock1  返回 1

(2)再次设置 返回 0
setnx lock 1

(3) get lock1


B:解决死锁

检测到锁已超时,即当前的时间大于键 lock.foo 的值,P4会执行以下操作
GETSET lock1 <current Unix timestamp + lock timeout + 1>
由于 GETSET 操作在设置键的值的同时,还会返回键的旧值,通过比较键 lock.foo 的旧值是否小于当前时间,可以判断进程是否已获得锁


值得注意的是,在进程释放锁,即执行 DEL lock.foo 操作前,需要先判断锁是否已超时。如果锁已超时,那么锁可能已由其他进程获得,这时直接执行 DEL lock1 操作会导致把其他进程已获得的锁释放掉。


redis 获取当前时间,毫秒数
EVAL "local a=redis.call('TIME') ;return (a[1]*1000000+a[2])/1000 " 0

设置分布式锁
eval "if redis.call('setnx','locktest',1) == 1 then redis.call('expire','locktest',10) return 1 else return 0 end" 0

分布式锁10秒超时

因为分布式锁还需要超时机制,所以我们利用expire命令来设置,所以利用setnx+expire命令的核心代码如下:

public boolean tryLock(String key,String requset,int timeout) {
    Long result = jedis.setnx(key, requset);
    // result = 1时,设置成功,否则设置失败
    if (result == 1L) {
        return jedis.expire(key, timeout) == 1L;
    } else {
        return false;
    }
}

上面的步骤是有问题的,setnx和expire是分开的两步操作,不具有原子性,如果执行完第一条指令应用异常或者重启了,锁将无法过期。

一种改善方案就是使用Lua脚本来保证原子性(包含setnx和expire两条指令)

2. 使用Lua脚本(包含setnx和expire两条指令)

public boolean tryLock_with_lua(String key, String UniqueId, int seconds) {
    String lua_scripts = "if redis.call('setnx',KEYS[1],ARGV[1]) == 1 then" +
            "redis.call('expire',KEYS[1],ARGV[2]) return 1 else return 0 end";
    List<String> keys = new ArrayList<>();
    List<String> values = new ArrayList<>();
    keys.add(key);
    values.add(UniqueId);
    values.add(String.valueOf(seconds));
    Object result = jedis.eval(lua_scripts, keys, values);
    //判断是否成功
    return result.equals(1L);
}
分享到:
评论

相关推荐

    Java基于redis实现分布式锁代码实例

    通过使用 Redis 的 setnx 命令和 expire 命令,可以实现分布式锁的功能。但是,需要注意的是,在实现分布式锁时,需要考虑到各种可能的异常情况,例如服务器挂掉等,并且需要对分布式锁进行优化,例如加过期时间,...

    详解使用Redis SETNX 命令实现分布式锁

    **使用SETNX实现分布式锁** 分布式锁的基本思想是,当多个进程或线程试图访问共享资源时,只有一个能获得锁并执行操作。在Redis中,我们可以使用SETNX命令来创建一个唯一的键(例如`lock.foo`),作为锁的标识。...

    redis实现分布式锁,自旋式加锁,lua原子性解锁

    本文将深入探讨如何使用Redis实现分布式锁,以及如何利用自旋式加锁和Lua脚本实现原子性解锁。 首先,我们来理解分布式锁的基本概念。分布式锁是在多节点之间共享资源时,用于协调各个节点的访问控制机制。在分布式...

    基于Redis方式实现分布式锁

    ### 基于Redis方式实现分布式锁 #### 分布式锁概述 分布式锁是一种常见的分布式系统协调机制,用于控制分布式环境下的多个...通过以上步骤,我们可以有效地使用Redis实现分布式锁的功能,提高系统的稳定性和性能。

    分布式锁实现(基于redis-mysql)1

    Redis是一个内存数据库,其命令执行是单线程的,这使得它非常适合用来实现分布式锁。Redis提供了`SETNX`命令,该命令在键不存在时设置键值,具有原子性。在Java中,我们可以使用以下代码片段来实现基于Redis的分布式...

    用Redis实现分布式锁_redis_分布式_

    Redis,作为一个高性能的键值存储系统,常被用于实现分布式锁,因为它提供了丰富的数据类型和原子操作。本教程将深入探讨如何利用Redis来构建分布式锁。 一、Redis分布式锁的优势 1. 响应速度:Redis是内存数据库...

    使用Redis实现分布式锁.zip

    Redis,一个高性能的键值存储系统,被广泛用作实现分布式锁的工具,因其高可用性、快速响应和丰富的数据结构支持。本文将深入探讨如何利用Redis实现分布式锁,并对比其与信号量的区别。 一、Redis分布式锁 1. **...

    redis分布式锁及会出现的问题解决

    总之,Redis 分布式锁的实现需要考虑各种异常情况,确保其可靠性和安全性。正确处理加锁、解锁以及超时机制,是构建健壮的分布式锁的关键。同时,根据具体业务场景选择合适的解决方案,如使用带有事务支持的 Redis ...

    redis和redisson实现分布式锁

    Redis作为一款高性能的键值存储系统,常被用作实现分布式锁的工具,而Redisson是基于Redis的Java客户端,提供了丰富的数据结构和服务功能,包括对分布式锁的支持。本文将深入探讨如何使用Redis和Redisson来构建...

    php redis setnx分布式锁简单原理解析

    以下是一个简单的PHP代码示例,用于演示如何使用Redis的`setnx`实现分布式锁: ```php header("Content-type:text/html;charset=utf-8"); $redis = new Redis(); $redis-&gt;connect('127.0.0.1', 6379); echo ...

    springboot redis zookeeperlock rabbit实现的分布式锁

    本项目基于SpringBoot框架,结合Redis、Zookeeper和RabbitMQ实现了分布式锁,让我们一起深入探讨这三个组件在分布式锁中的作用和实现机制。 **SpringBoot** 是一个轻量级的Java开发框架,它简化了新Spring应用的...

    基于Redis实现分布式锁以及任务队列

    通过`setnx`实现分布式锁的互斥性,借助有序集合处理任务队列,可以有效应对高并发场景下的并发控制和任务调度问题,提高系统的稳定性和效率。在实际应用中,需要注意锁的生命周期管理,避免死锁和资源浪费,同时...

    java面试最全八股文

    * SETNX实现分布式锁 * 锁的释放 2. 使用Memcached实现分布式锁 3. 使用ZooKeeper实现分布式锁 获取锁 释放锁 获取锁 释放锁 Spring Cloud面试题 什么是 Spring Cloud? 使用 Spring Cloud 有什么优势? 服务注册和...

    redis分布式锁.zip

    下面将详细介绍如何使用 Redis 实现分布式锁以及其中可能遇到的问题和解决方案。 首先,我们需要理解分布式锁的基本概念。分布式锁是一种在分布式系统中协调不同节点对共享资源访问的机制。它确保在任何时刻只有一...

    基于Spring Boot框架的分布式锁服务.zip

    Redis分布式锁利用Redis的SETNX命令实现分布式锁,确保在分布式环境下对资源的互斥访问。 Redisson分布式锁使用Redisson库提供的分布式锁实现,提供更高级的功能,如锁的自动续期和可重入锁。 2. 锁的续期和释放...

    分布式锁原理讲解视频资料

    2. 基于缓存的分布式锁:使用Redis等内存数据库,通过SETNX命令实现原子性操作,设置超时时间防止死锁。还可以结合lua脚本增强安全性。 3. 基于Zookeeper的分布式锁:利用Zookeeper的临时有序节点和watcher特性,...

    浅谈分布式锁

    2. 基于缓存实现:常见的缓存组件有Redis,利用Redis提供的数据结构(如setnx命令)和特性(如过期时间设置)来实现分布式锁。但要注意Redis的复制是异步的,且单点故障可能会导致锁失效。 3. 基于ZooKeeper实现:...

    springboot基于redis分布式锁

    不过,以上代码提供了一个基本的实现思路,帮助你理解如何在SpringBoot应用中使用Redis实现分布式锁。 通过提供的Word文档,你应该能够找到更详细的配置和使用步骤。记得在实际项目中根据具体需求进行调整,确保...

    解析分布式锁之redis实现1

    在Redis中,可以通过`SETNX`命令来实现分布式锁。`SETNX`命令用于设置键值,只有当键不存在时才会设置成功,并返回1,否则返回0。我们可以利用这个特性来尝试获取锁。例如: ```java // 获取锁 long timestamp = ...

Global site tag (gtag.js) - Google Analytics