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

这里写目录标题

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; //等待一段时候后,重新执行开始的逻辑
		}
	}
}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值