2022-11 | Redis命令SET SETEX SETNX语法及描述

本文详细介绍了Redis中的SET、SETEX和SETNX命令的使用,以及基于这些命令实现的简单死锁处理机制。SET命令允许设置键值对并可选设置存活时间,SETEX则是原子性地设置键值对并指定生存时间。SETNX在键不存在时设置键值对,常用于简单的锁实现。在死锁处理中,通过GETSET来检查并更新锁的过期时间,确保锁的安全释放。文章还提醒在持有锁期间定期检查锁的过期时间,以增强锁的健壮性。

这里写目录标题

SET

语法

SET key value [EX seconds|PX milliseconds|EXAT unix-time-seconds|PXAT unix-time-milliseconds|KEEPTTL] [NX|XX] [GET]

SETEX

可以通过SET实现

语法

SETEX key ttl value

返回值:RESP simple string(可以通俗的理解为字符串OK)

描述

设置key=value,键存活时间ttl秒。

上述命令等价于下面的命令

SET key value
EXPIRE key ttl

SETEX命令是原子的,可以通过在MULTI/EXEC块中使用前两个命令重现。

SETEX是作为序列操作时的更快的解决方案,当Redis用于缓存时,这个命令使用频繁。

存活时间只支持整数秒,否则报错。

例子

redis> SETEX keyName 10 value
"OK"

SETNX

可以通过SET实现

语法

SETNX key value

返回值:成功设置键返回1,否则返回0

描述

如果键不存在,则设置key=value;如果键存在,不进行任何操作。

设计模式:SETNX实现锁

注意:

  1. Redlock算法实现复杂,通过下面的模式实现还是差点意思,但是下面的模式在实现锁方面能提供很好的保证和容错。

SETNX曾一度被用来作为锁函数,获取锁的命令如下:

GETSET lock <currentUnixTimestamp + lockTimeout + 1>

lock的值为过期点的时间戳

死锁处理

如果客户端因为某种原因无法释放锁,此时如何处理?

正确的操作:

  1. 用户2通过SETNX获取锁

  2. 如果获取失败,通过GET查看锁过期时间(因为设置键值对时值表示的过期时间)

  3. 如果锁没有过期,则休眠若干秒后重新获取

  4. 如果锁过期了,通过如下命令尝试获取锁

    GETSET lock <currentUnixTimestamp + lockTimeout + 1>
    
  5. GETSET会返回用户1设置的旧值,因此可以通过判断旧值是否被修改得出锁是否被其他人获取,如果没有则获取;如果被别人获取了,则重新开始第1步

    注意:GETSET会成功设置值,并返回旧值,所以用户2执行GETSET会把用户3设置的值修改了,但是相当于把时间延后几秒,整体来说不打紧。

  6. 如果用户3先获取了,则旧值已经变成了用户3设置的值,那么用户2放弃获取锁

上述操作对应的伪代码如下

//当前时间戳假设为10
int getLock = SETNX lock 30;
if (getLock == 1) {
	System.out.println("成功获取到锁");
} else {
	//说明锁被其他客户端持有
	int expireTimestamp = GET lock;
	int currentTimestamp = 15;
	if (currentTimestamp > expireTimestamp) {
		//说明锁已经过期了
		int getLockAgain = GETSET lock 40;
		if (getLockAgain == expireTimestamp) {
			System.out.println("成功获取到锁");
		} else {
			System.out.println("获取锁失败,锁已经被其他人先获取了");
			continue; //等待一段时候后,重新执行开始的逻辑
		}
	}
}

为了让锁算法更加健壮,客户端在没有释放锁前最好定期检查锁过期时间。

### RedisSETNX 命令使用方法 #### 什么是 SETNX? `SETNX` 是 Redis 中的一个原子性命令,其全称为 **SETEX IF NOT EXISTS**。该命令的作用是只有当指定的键不存在时才会设置键值对[^1]。 --- #### SETNX 的基本语法 以下是 `SETNX` 的标准语法: ```bash SETNX key value ``` - 参数说明: - `key`: 要设置的目标键名。 - `value`: 设置到目标键中的值。 返回值: - 当键不存在时成功设置,返回 `1`。 - 若键已经存在,则不执行任何操作,返回 `0`。 --- #### 改进版 SETNX 使用方式 Redis 提供了一个更强大的替代方案——通过扩展参数实现功能增强。可以结合 `NX` 和 `EX` 来完成类似的逻辑: ```bash SET key value NX EX seconds ``` - 参数解释: - `NX`: 表示仅在键不存在的情况下执行设置操作(等价于原始的 `SETNX` 功能)。 - `EX seconds`: 设定键的有效期,单位为秒。 例如: ```bash SET lock_key "123" NX EX 10 ``` 如果 `lock_key` 键尚不存在,则将其值设为 `"123"` 并使它在 10 秒后自动过期[^1]。 --- #### Java 实现示例 以下是一个基于 Spring Data Redis 的代码片段,展示如何利用 `SETNX` 或改进后的 `SET` 方法来实现分布式锁的功能[^2]: ```java @Override public boolean setNx(String key, String value, long time) { try { RedisCallback<String> callback = (connection) -> { JedisCommands commands = (JedisCommands) connection.getNativeConnection(); return commands.set(key, value, "NX", "PX", time); }; String result = redisTemplate.execute(callback); return !StringUtils.isEmpty(result); // 判断是否成功设置了键值对 } catch (Exception e) { logger.error("Error occurred while setting the key in Redis.", e); } return false; } ``` 此函数实现了带超时机制的 `SETNX` 操作,其中: - `time` 单位为毫秒 (`PX`)。 - 成功则返回 `true`;失败或发生异常则返回 `false`。 --- #### 应用场景:分布式锁 由于 `SETNX` 的特性决定了它的高可用性和线程安全性,在实际开发中常被用来构建简单的分布式锁解决方案。具体流程如下: - 尝试获取资源对应的唯一标识符作为键; - 如果当前无其他进程持有相同名称的锁,则创建新记录并赋予一定存活期限; - 同一时刻只有一个客户端能够获得许可从而进入临界区处理业务逻辑。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值