redis分布式锁(一)set NX实现 您所在的位置:网站首页 分布式锁用在什么场景 redis分布式锁(一)set NX实现

redis分布式锁(一)set NX实现

2024-07-12 14:14| 来源: 网络整理| 查看: 265

最近是一直在研究redis,本篇则主要想谈谈对redis的锁的理解。

文章目录 一、SETNX命令的使用二、SET实现1)命令说明:2)set get 可以对已经存在的值重新赋值3)可以设置过期时间 ex ttl4)NX 已经存在的值不能再次赋值5)XX:不存在的key不能赋值,只能修改已经存在的key的value 三、实现分布式锁1)命令基本实现2)图解3)项目中代码实现4)问题一:那为什么要使用PX/XX 去设置一个超时时间?5)问题二:设置了超时时间,就确保万无一失了吗? 四、总结 使用redis常用的两种加锁的机制:

SETNX命令SET命令 一、SETNX命令的使用

SETNX 是『SET if Not eXists』(如果不存在,则 SET)的简写。

SETNX key value 将 key 的值设为 value ,当且仅当 key 不存在。 若给定的 key 已经存在,则 SETNX 不做任何动作。

127.0.0.1:6379> SETNX test 'try' (integer) 1 127.0.0.1:6379> get test "try" 127.0.0.1:6379> SETNX test 'tryAgain' (integer) 0 127.0.0.1:6379> get test "try"

第一次给test赋值,返回表示成功;第二次再次尝试给test赋值,返回0,表示失败,并未再次操作,因为值已经存在。 比如有两个线程A和B,两个线程操作相同的key. 在这里插入图片描述 虽然流程上是能够走通的.

二、SET实现

如上的NX命令也就是简单介绍一下使用,一般说分布式锁NX命令其实是表达set 的一种命令,如下:

1)命令说明:

SET key value [EX seconds] [PX milliseconds] [NX|XX] 生存时间(TTL,以秒为单位) Redis 2.6.12 版本开始:(等同SETNX 、 SETEX 和 PSETEX) EX second :设置键的过期时间为 second 秒。 SET key value EX second 效果等同于 SETEX key second value 。 PX millisecond :设置键的过期时间为 millisecond 毫秒。 SET key value PX millisecond 效果等同于 PSETEX key millisecond value 。 NX :只在键不存在时,才对键进行设置操作。 SET key value NX 效果等同于 SETNX key value 。 XX :只在键已经存在时,才对键进行设置操作。

2)set get 可以对已经存在的值重新赋值 127.0.0.1:6379> set test1 value OK 127.0.0.1:6379> get test1 "value" #可以重新对已经存在的值赋值 127.0.0.1:6379> set test1 new-value OK 127.0.0.1:6379> get test1 "new-value" 3)可以设置过期时间 ex ttl #设置过期时间为10000秒 127.0.0.1:6379> set test1-expire-time 'hello' ex 10000 OK 127.0.0.1:6379> get test1-expire-time "hello" #ttl 获取剩余过期时间 127.0.0.1:6379> ttl test1-expire-time (integer) 9990 127.0.0.1:6379> ttl test1-expire-time (integer) 9963 127.0.0.1:6379> ttl test1-expire-time (integer) 9876 4)NX 已经存在的值不能再次赋值 #NX:已经存在的值不能再次赋值 127.0.0.1:6379> set not-test1-key 'hello' NX OK 127.0.0.1:6379> get not-test1-key "hello" 127.0.0.1:6379> set not-test1-key 'hello1' NX (nil) 127.0.0.1:6379> get not-test1-key "hello" 5)XX:不存在的key不能赋值,只能修改已经存在的key的value #XX:未存在的key不能赋值,只能修改已经存在的key的value 127.0.0.1:6379> EXISTS exists-key (integer) 0 127.0.0.1:6379> set exists-key 'value' XX (nil) 127.0.0.1:6379> set exists-key 'value' OK 127.0.0.1:6379> set exists-key 'value-new' XX OK 127.0.0.1:6379> get exists-key "value-new" 三、实现分布式锁 1)命令基本实现

命令 SET resource-name anystring NX EX max-lock-time 是一种在 Redis 中实现锁的简单方法

#给lock设置了过期时间为60000毫秒(也可以用ex 6000,单位就变成了秒),当用NX再次赋值,则返回nil,不能重入操作 127.0.0.1:6379> set lock true NX px 60000 OK 127.0.0.1:6379> set lock true NX px 6000 (nil) 127.0.0.1:6379> get lock "true" 127.0.0.1:6379> ttl lock (integer) 43 #时间过期后再次get,返回nil,表明key 为 lock的锁已经释放 127.0.0.1:6379> get lock (nil)

如果setnx 返回ok 说明拿到了锁;如果setnx 返回 nil,说明拿锁失败,被其他线程占用。 换成客户端服务器则是如下: 客户端执行以上的命令: 如果服务器返回 OK ,那么这个客户端获得锁。 如果服务器返回 NIL ,那么客户端获取锁失败,可以在稍后再重试。

2)图解

如上过程通过一个图解一下: 在这里插入图片描述

3)项目中代码实现

如下是程序中写的redisConfig。采用了jsdisCluster的set方法。详情:jedis set 的四个重载方法

@Override public String lock(String key,long expireSecond) { final String value = String.valueOf(System.currentTimeMillis()); //nx : not exists, 只有key 不存在时才把key value set 到redis final String nxxx = "NX"; //ex : seconds 秒 final String expx = "EX"; boolean ret; if(expireSecond 0L; else //设置key的过期时间是expireSecond ret = "ok".equalsIgnoreCase(jedisCluster.set(key, value, nxxx, expx, expireSecond)); if(ret){ return value; }else{ return null; } } 4)问题一:那为什么要使用PX/XX 去设置一个超时时间?

是怕进程A不讲道理啊,锁没等释放呢,万一崩了,直接原地把锁带走了,导致系统中谁也拿不到锁。

5)问题二:设置了超时时间,就确保万无一失了吗?

如果进程A又不讲道理,操作锁内资源超过笔者设置的超时时间,那么就会导致其他进程拿到锁,等进程A回来了,回手就是把其他进程的锁删了 在这里插入图片描述 该如何解决如上场景呢?可以加一层判定,当自己的进程结束或者过期,若value不是自己的值,则不进行删除操作流程。

/** * * @param key * @param keySign 可为空,为空则不断是否为上次获得的锁 * @return */ @Override public boolean unlock(final String key, final String keySign) { if(StringUtils.isNotBlank(keySign)){ String val = jedisCluster.get(key); if(!keySign.equals(val)) { return false; } } if(jedisCluster.del(key) return false; }else{ return true; } } return true; } 四、总结

目前项目中是使用了jedis客户端来操作Redis cluster。以上操作都得经过程序员的手动编码,以及能不能保证原子性的问题,当然业务量不大或者并发不大的情况还是很好用的。 下篇则讲述redission如何实现分布式锁?



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有