精华内容
下载资源
问答
  • 1. redis加锁分类 redis能用的的加锁命令分表是INCR、SETNX、SET 2. 第一种锁命令INCR 这种加锁的思路是, key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作进行加一。 然后其它用户在执行 INCR ...
  • redis加锁解锁 代码实现 @Service public class RedisLockService { private static final Long SUCCESS = 1L; @Resource private RedisTemplate<String, Object> redisTemplate; /** * 加锁 * @...

    redis加锁解锁 代码实现

    @Service
    public class RedisLockService {
        private static final Long SUCCESS = 1L;
    
        @Resource
        private RedisTemplate<String, Object> redisTemplate;
    
        /**
         *  加锁
         * @return 状态
         */
        public boolean lock(String key, String value, int millisecond, int tryCount) {
            // 重试次数最大5次
            if (tryCount > 5) {
                tryCount = 5;
            }
            try {
                String script =
                        "local key = KEYS[1]; local value = ARGV[1]; if redis.call('set', key, value, 'NX' ,'PX', "
                                + millisecond + ") then return 1 else return 0 end";
                DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>(script, Long.class);
                Long result = redisTemplate
                        .execute(redisScript, Collections.singletonList(key), Collections.singletonList(value));
                // 判断结果
                if (RELEASE_SUCCESS.equals(result)) {
                    return true;
                }
            } catch (Exception ex) {
                // redis命中失败或连接有问题时,重试机制
                // 重试次数
                if (tryCount == 0) {
                    return false;
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    return false;
                }
                System.out.println(tryCount);
                // 重试机制
                return lock(key, value, millisecond, tryCount - 1);
            }
            return false;
        }
    
    
        /**
         * 解锁
         * @return 状态
         */
        public boolean unlock(String key) {
            return redisTemplate.delete(key);
        }
        /**
         * 释放分布式锁
         *
         * @param lockKey 锁
         * @param value   请求标识
         * @return 是否释放成功
         */
        public boolean releaseLock(String lockKey, String value) {
    
            String script =
                    "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
            DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>(script, Long.class);
            Long execute =
                    redisTemplate.execute(redisScript, Collections.singletonList(lockKey), Collections.singletonList(value));
            if (RELEASE_SUCCESS.equals(execute)) {
                return true;
            }
            return false;
    
        }
    }
    
    展开全文
  • //获得锁 RLock locker = RedisUtil.getClient().getLock("锁的名字,例:Locker:TestLockA"); //上锁 locker.lock(); try { /* 你自己看的业务代码 此处省略成千上万个BUG,祝君好运!... if (locker.isLock
    //获得锁
    RLock locker = RedisUtil.getClient().getLock("锁的名字,例:Locker:TestLockA");
    
    //上锁
    locker.lock();
    
    try {
    	
    	/*
    	你自己看的业务代码
    	此处省略成千上万个BUG,祝君好运!!!
    	*/
    	
    } catch (Exception e) {
    
        e.printStackTrace();
        
    } finally {
    
    	//此处判断是否被锁定或者是否被当前线程持有
        if (locker.isLocked() && locker.isHeldByCurrentThread()) {
        
    		//解锁
            locker.unlock();
            
        }
        
    }
    
    展开全文
  • redis加锁的几种方法

    2020-11-24 14:04:31
    1、 客户端A请求服务器获取key的值为1表示获取了锁 2、 客户端B也去请求服务器获取key的值为2表示获取锁失败 3、 客户端A执行代码完成,删除锁...$redis->incr($key); $redis->expire($key, $ttl); //设置生成时间为1秒
    1. redis加锁分类
        redis能用的的加锁命令分表是INCR、SETNX、SET
    2. 第一种锁命令INCR
        这种加锁的思路是, key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作进行加一。
        然后其它用户在执行 INCR 操作进行加一时,如果返回的数大于 1 ,说明这个锁正在被使用当中。
    1、 客户端A请求服务器获取key的值为1表示获取了锁
    2、 客户端B也去请求服务器获取key的值为2表示获取锁失败
    3、 客户端A执行代码完成,删除锁
    4、 客户端B在等待一段时间后在去请求的时候获取key的值为1表示获取锁成功
    5、 客户端B执行代码完成,删除锁
    
    $redis->incr($key);
    $redis->expire($key, $ttl); //设置生成时间为1秒
    
    1. 第二种锁SETNX
        这种加锁的思路是,如果 key 不存在,将 key 设置为 value
        如果 key 已存在,则 SETNX 不做任何动作
    1、 客户端A请求服务器设置key的值,如果设置成功就表示加锁成功
    2、 客户端B也去请求服务器设置key的值,如果返回失败,那么就代表加锁失败
    3、 客户端A执行代码完成,删除锁
    4、 客户端B在等待一段时间后在去请求设置key的值,设置成功
    5、 客户端B执行代码完成,删除锁
    
    $redis->setNX($key, $value);
    $redis->expire($key, $ttl);
    
    1. 第三种锁SET
        上面两种方法都有一个问题,会发现,都需要设置 key 过期。那么为什么要设置key过期呢?如果请求执行因为某些原因意外退出了,导致创建了锁但是没有删除锁,那么这个锁将一直存在,以至于以后缓存再也得不到更新。于是乎我们需要给锁加一个过期时间以防不测。
        但是借助 Expire 来设置就不是原子性操作了。所以还可以通过事务来确保原子性,但是还是有些问题,所以官方就引用了另外一个,使用 SET 命令本身已经从版本 2.6.12 开始包含了设置过期时间的功能。
    1、 客户端A请求服务器设置key的值,如果设置成功就表示加锁成功
    2、 客户端B也去请求服务器设置key的值,如果返回失败,那么就代表加锁失败
    3、 客户端A执行代码完成,删除锁
    4、 客户端B在等待一段时间后在去请求设置key的值,设置成功
    5、 客户端B执行代码完成,删除锁
    
    $redis->set($key, $value, array('nx', 'ex' => $ttl)); //ex表示秒
    
    展开全文
  • redis加锁分类 redis能用的的加锁命令分表是INCR、SETNX、SET 第一种锁命令INCR 这种加锁的思路是, key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作进行加一。 然后其它用户在执行 INCR 操作...
    1. redis加锁分类
      redis能用的的加锁命令分表是INCR、SETNX、SET
    2. 第一种锁命令INCR
      这种加锁的思路是, key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作进行加一。
      然后其它用户在执行 INCR 操作进行加一时,如果返回的数大于 1 ,说明这个锁正在被使用当中。

    1、 客户端A请求服务器获取key的值为1表示获取了锁
    2、 客户端B也去请求服务器获取key的值为2表示获取锁失败
    3、 客户端A执行代码完成,删除锁
    4、 客户端B在等待一段时间后在去请求的时候获取key的值为1表示获取锁成功
    5、 客户端B执行代码完成,删除锁

    $redis->incr($key);
    $redis->expire($key, $ttl); //设置生成时间为1秒
    
    1. 第二种锁SETNX
      这种加锁的思路是,如果 key 不存在,将 key 设置为 value
      如果 key 已存在,则 SETNX 不做任何动作

    1、 客户端A请求服务器设置key的值,如果设置成功就表示加锁成功
    2、 客户端B也去请求服务器设置key的值,如果返回失败,那么就代表加锁失败
    3、 客户端A执行代码完成,删除锁
    4、 客户端B在等待一段时间后在去请求设置key的值,设置成功
    5、 客户端B执行代码完成,删除锁

    $redis->setNX($key, $value);
    $redis->expire($key, $ttl);
    
    1. 第三种锁SET
      上面两种方法都有一个问题,会发现,都需要设置 key 过期。那么为什么要设置key过期呢?如果请求执行因为某些原因意外退出了,导致创建了锁但是没有删除锁,那么这个锁将一直存在,以至于以后缓存再也得不到更新。于是乎我们需要给锁加一个过期时间以防不测。
      但是借助 Expire 来设置就不是原子性操作了。所以还可以通过事务来确保原子性,但是还是有些问题,所以官方就引用了另外一个,使用 SET 命令本身已经从版本 2.6.12 开始包含了设置过期时间的功能。

    1、 客户端A请求服务器设置key的值,如果设置成功就表示加锁成功
    2、 客户端B也去请求服务器设置key的值,如果返回失败,那么就代表加锁失败
    3、 客户端A执行代码完成,删除锁
    4、 客户端B在等待一段时间后在去请求设置key的值,设置成功
    5、 客户端B执行代码完成,删除锁

    $redis->set($key, $value, array('nx', 'ex' => $ttl));  //ex表示秒
    
    1. 其它问题
      虽然上面一步已经满足了我们的需求,但是还是要考虑其它问题?
      1、 redis发现锁失败了要怎么办?中断请求还是循环请求?
      2、 循环请求的话,如果有一个获取了锁,其它的在去获取锁的时候,是不是容易发生抢锁的可能?
      3、 锁提前过期后,客户端A还没执行完,然后客户端B获取到了锁,这时候客户端A执行完了,会不会在删锁的时候把B的锁给删掉?

    2. 解决办法
      针对问题1:使用循环请求,循环请求去获取锁
      针对问题2:针对第二个问题,在循环请求获取锁的时候,加入睡眠功能,等待几毫秒在执行循环
      针对问题3:在加锁的时候存入的key是随机的。这样的话,每次在删除key的时候判断下存入的key里的value和自己存的是否一样

    do { //针对问题1,使用循环
    $timeout = 10;
    $roomid = 10001;
    $key = ‘room_lock’;
    KaTeX parse error: Expected group after '_' at position 14: value = 'room_̲'.roomid; //分配一个随机的值针对问题3
    i s L o c k = R e d i s : : s e t ( isLock = Redis::set( isLock=Redis::set(key, $value, ‘ex’, t i m e o u t , ′ n x ′ ) ; / / e x 秒 i f ( timeout, 'nx');//ex 秒 if ( timeout,nx);//exif(isLock) {
    if (Redis::get($key) == KaTeX parse error: Expected '}', got 'EOF' at end of input: … Redis::del(key);
    continue;//执行成功删除key并跳出循环
    }
    } else {
    usleep(5000); //睡眠,降低抢锁频率,缓解redis压力,针对问题2
    }
    } while(!$isLock);
    7. 另外一个锁
    以上的锁完全满足了需求,但是官方另外还提供了一套加锁的算法,这里以PHP为例

    $servers = [
    [‘127.0.0.1’, 6379, 0.01],
    [‘127.0.0.1’, 6389, 0.01],
    [‘127.0.0.1’, 6399, 0.01],
    ];

    $redLock = new RedLock($servers);
    
    //加锁
    $lock = $redLock->lock('my_resource_name', 1000);
    
    //删除锁
    $redLock->unlock($lock)
    

    上面是官方提供的一个加锁方法,就是和第6的大体方法一样,只不过官方写的更健壮。所以可以直接使用官方提供写好的类方法进行调用。官方提供了各种语言如何实现锁。

    分布式锁文章:
    Redis实现分布式锁

    漫画理解:
    程序员小灰—《什么是分布式锁》

    原文:https://blog.csdn.net/liuyongchen0824/article/details/88341981

    展开全文
  • Redis加锁的几种实现

    千次阅读 2020-07-07 11:24:32
    我们经常在工作中会碰到一些重复请求、并发等问题,而给资源加锁是一种不错的手段。我们今天就整理下使用redis作为分布式锁的几种实现。 redis可以用于几个命令是:INCR、SETNX和SET。 1. 使用INCR加锁 这种加锁的...
  • redis加锁并设置过期时间

    千次阅读 2020-06-28 10:51:31
    @Service public class RedisService { /** redis锁前缀 */ private static final String REDIS_LOCK_PREFIX = "LOCK_SMART_WARING_"; @Autowired ... * 加锁并设置过期时间 * * @param lockName
  • redis加锁的几种实现

    万次阅读 多人点赞 2019-03-08 10:20:23
    1. redis加锁分类 redis能用的的加锁命令分表是INCR、SETNX、SET 2. 第一种锁命令INCR 这种加锁的思路是, key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作进行加一。 然后其它用户在执行 INCR...
  • php利用redis加锁

    2018-03-07 17:16:12
    1.redis锁引入该类 /** * Redis锁操作类 * Date: 2016-06-30 * Author: fdipzone * Ver: 1.0 * * Func: * public lock 获取锁 * public unlock 释放锁 * private connect 连接 */ class RedisLoc
  • 使用Redis的 SETNX 命令可以实现分布式锁 SETNX key value 返回值 返回整数,具体为- 1,当 key 的值被设置- 0,当 key 的值没被设置 分布式锁使用 import redis.clients.jedis.Jedis; import redis....
  • 使用Redis的 SETNX 命令可以实现分布式锁 SETNX key value 返回值 返回整数,具体为- 1,当 key 的值被设置- 0,当 key 的值没被设置 转载于:https://www.cnblogs.com/Andrew520/p/10918444.html...
  • 此方法通常用于给redis某个key进行加锁 例如: keyA需要加锁,则: $redis->set(keyA_lock, 1, array('nx', 'ex' => 1)); 判断keyA_lock是否存在 如果存在,则keyA已被上锁 解锁的时候,删除相关锁
  • 1、redis下载安装 Github下载地址:https://github.com/MicrosoftArchive/redis/releases 安装过程不做写明 1、VS引用StackExchange.Redis 通过“工具”=》“库程序包管理器”=》“程序包管理器控制台” pm>...
  • 背景说明 在程序开发过程中,通常会...本文简单介绍PHP中使用redis来实现加锁和解锁。实现方式参考了redis官方文档。 示例代码 代码环境:单redis实例,PHP5.6及以上,且需开启redis扩展 $redis = new \Redis(); ...
  • try{ //防止并发重复充值 if(cacheService.hsetnx(MemberRedisKey.MEMBER_RECHARGE_FLAG, billEntity.getOrderId(), 1)){ memberAccountService.doRechargeHandle(billEntity.getMemberId(), billEntity....
  • redis加锁、解锁

    2021-08-23 16:32:44
    在Java中,关于锁我想大家都很熟悉。在并发编程中,我们通过锁,来...在沙滩上踩一脚,留下自己的脚印,就对应了加锁操作。其他进程或者线程,看到沙滩上已经有脚印,证明锁已被别人持有,则等待。 解锁 把脚印从沙滩上
  • redis加锁的常见几种方式

    千次阅读 多人点赞 2021-05-23 03:55:32
    redis加锁的常见几种方式,redis中加锁是比价常见的操作,为了防止并发情况下产生的各种内存分配问题,而选择如何正确高效的加锁,才是我们应该需要知道和了解的,常码字不易,出精品更难,没有特别幸运,那么请先...
  • redis加锁工具RedisLockUtils

    千次阅读 2019-03-04 19:07:07
    有很多大佬介绍分布式锁实现方式的文章,在这主要记录一个线程的redis加锁工具 https://www.cnblogs.com/0201zcr/p/5942748.html import java.util.ArrayList; import java.util.List; import org.apache.commons....
  • 这篇文章主要介绍了浅谈redis加锁常用几种方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧 一、incr加锁 connect('127.0.0.1');...
  • redis加锁控制

    2018-05-18 10:26:58
    1.redis加锁 需要看 加锁的是什么方法 ,比如买标的, 加锁的就是要 加锁标的 id,加锁活动 加锁活动的id 其他的类似, 共享数据 需要加锁,防止用户过多造成并发问题...
  • redis加锁

    2021-04-30 11:08:39
    这是我第一篇博客,激动Redis加锁 Redis加锁 加锁的方式有很多种,我们来说现在用的比较多的一种—redis加锁 下面我们来看一个实例: String keyValue = UUID.randomUUID().toString();//定义一个唯一值,作用:这个...
  • redis加锁 1. redis加锁分类 redis能用的的加锁命令分表是INCR、SETNX、SET 2. 第一种锁命令INCR 这种加锁的思路是, key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作进行加一。 然后其它用户...
  • redis加锁解锁

    2021-10-26 14:36:13
    import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; import javax.annotation.Resource; @Component public class RedisLockCommon { @...
  •  logger.error("redis.lock.setnx is error", e);  // 避免成功获取到锁,但是未成功设置过期时间  redisClient.expire("lockKey", 60*60);//一小时  }    reutrn hasLock; } //释放锁 releaseLock() {  ...
  • php redis 加锁与解锁

    2018-06-17 03:37:48
    php+redis 实现加锁与解锁操作 业务背景:在房间棋牌游戏中需要用到锁来防止并发操作引起的 redis 数据脏读问题;例如添加用户进入房间的动作: 并发的情况下,get RoomUsers 会有脏读现象; 解决思路:加锁房间来...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 39,577
精华内容 15,830
关键字:

redis加锁

redis 订阅