语法

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

可用版本

≥ 1.0.0

时间复杂度

$O(1)$

ACL类别

@write, @string, @slow

设置 key 保存字符串类型的 value。如果 key 已经持有一个值,它将被覆盖,不管它是什么类型。在成功的 SET 操作中,任何先前与 key 相关的生存时间都会被丢弃。

选项

SET 命令支持以下选项:

  • EX seconds — 设置指定的过期时间,单位为秒。
  • PX milliseconds — 设置指定的过期时间,单位是毫秒。
  • EXAT timestamp-seconds — 设置指定的 Unix 时间,key 将在该时间过期,单位是秒。
  • PXAT timestamp-milliseconds — 设置指定的 Unix 时间,以毫秒为单位,key 将在该时间过期。
  • NX — 只有在 key 不存在的情况下才会设置它。
  • XX — 只设置已经存在的 key。
  • KEEPTTL — 保留与 key 相关的生存时间。
  • GET — 返回存储在 key 的旧字符串,如果 key 不存在,则返回 nil。如果存储在键上的值不是字符串,将返回一个错误,并中止 SET 操作。

注意:由于 SET 命令选项可以取代 SETNXSETEXPSETEXGETSET,因此在 Redis 的未来版本中,这些命令有可能被废弃,并最终被删除。

返回值

返回简单的字符串:如果 SET 被正确执行,则返回 OK。

返回 Null:(nil)如果 SET 操作没有被执行,因为用户指定了 NXXX 选项,但条件没有被满足。

如果命令是用 GET 选项发出的,上述情况不适用。相反,它的返回如下,不管 SET 是否真的被执行:

返回批量字符串:存储在 key 的旧字符串值。

返回 Null:(nil)如果键不存在。

示例 1

1
2
3
4
redis> SET js "Rain rain"
OK
redis> GET js
"Rain rain"

模式

注意:不鼓励使用该模式,推荐使用 Redlock 算法,该算法只是实现起来更复杂一点,但能提供更好的保证和容错性。

借助 Redis 实现锁系统的一个简单方法是使用 SET resource-name anystring NX EX max-lock-time 命令。

如果上述命令返回 OK,客户端可以获得锁(如果命令返回 Nil,则在一段时间后重试),而移除锁只需使用 DEL 命令。

在过期时间到达后,该锁将被自动释放。

可以通过修改解锁模式来使这个系统更加强大,具体如下:

  • 不要设置一个固定的字符串,而是设置一个不可猜测的大的随机字符串,称为 token。
  • 与其用 DEL 释放锁,不如发送一个脚本,只有在值匹配的情况下才删除钥匙。

这就避免了客户端在过期后试图释放锁,删除由另一个后来获得锁的客户端创建的密钥。

释放锁的脚本内容类似于以下:

1
2
3
4
5
6
if redis.call("get",KEYS[1]) == ARGV[1]
then
return redis.call("del",KEYS[1])
else
return 0
end

该脚本应该用 EVAL ...script... 1 resource-name token-value 来调用。

历史记录

  • 从 Redis 2.6.12 版本开始:增加了 EXPXNXXX 选项。
  • 从 Redis 6.0.0 版本开始:增加了 KEEPTTL 选项。
  • 从 Redis 6.2.0 版本开始:增加了 GETEXATPXAT 选项。
  • 从 Redis 7.0.0 版本开始:允许 NXGET 选项一起使用。

(END)