一、SET key value [EX seconds] [PX milliseconds] [NX|XX]
如果 key 已經持有其他值, SET 就覆寫舊值,無視類型。
對於某個原本帶有生存時間(TTL)的鍵來說, 當 SET 命令成功在這個鍵上執行時, 這個鍵原有的 TTL 將被清除。
二、可選參數
從 Redis 2.6.12 版本開始, SET 命令的行為可以通過一系列參數來修改:
- EX second :設置鍵的過期時間為 second 秒。 SET key value EX second 效果等同於 SETEX key second value 。
- PX millisecond :設置鍵的過期時間為 millisecond 毫秒。 SET key value PX millisecond 效果等同於 PSETEX keymillisecond value 。
- NX :只在鍵不存在時,才對鍵進行設置操作。 SET key value NX 效果等同於 SETNX key value 。
- XX :只在鍵已經存在時,才對鍵進行設置操作。
因為 SET 命令可以通過參數來實現和 SETNX 、 SETEX 和 PSETEX 三個命令的效果,所以將來的 Redis 版本可能會廢棄並最終移除 SETNX 、 SETEX 和 PSETEX 這三個命令。
- 三、可用版本:
- >= 1.0.0
- 四、時間復雜度:
- O(1)
- 五、返回值:
-
在 Redis 2.6.12 版本以前, SET 命令總是返回 OK 。
從 Redis 2.6.12 版本開始, SET 在設置操作成功完成時,才返回 OK 。如果設置了 NX 或者 XX ,但因為條件沒達到而造成設置操作未執行,那么命令返回空批量回復(NULL Bulk Reply)。
# 對不存在的鍵進行設置 redis 127.0.0.1:6379> SET key "value" OK redis 127.0.0.1:6379> GET key "value" # 對已存在的鍵進行設置 redis 127.0.0.1:6379> SET key "new-value" OK redis 127.0.0.1:6379> GET key "new-value" # 使用 EX 選項 redis 127.0.0.1:6379> SET key-with-expire-time "hello" EX 10086 OK redis 127.0.0.1:6379> GET key-with-expire-time "hello" redis 127.0.0.1:6379> TTL key-with-expire-time (integer) 10069 # 使用 PX 選項 redis 127.0.0.1:6379> SET key-with-pexpire-time "moto" PX 123321 OK redis 127.0.0.1:6379> GET key-with-pexpire-time "moto" redis 127.0.0.1:6379> PTTL key-with-pexpire-time (integer) 111939 # 使用 NX 選項 redis 127.0.0.1:6379> SET not-exists-key "value" NX OK # 鍵不存在,設置成功 redis 127.0.0.1:6379> GET not-exists-key "value" redis 127.0.0.1:6379> SET not-exists-key "new-value" NX (nil) # 鍵已經存在,設置失敗 redis 127.0.0.1:6379> GEt not-exists-key "value" # 維持原值不變 # 使用 XX 選項 redis 127.0.0.1:6379> EXISTS exists-key (integer) 0 redis 127.0.0.1:6379> SET exists-key "value" XX (nil) # 因為鍵不存在,設置失敗 redis 127.0.0.1:6379> SET exists-key "value" OK # 先給鍵設置一個值 redis 127.0.0.1:6379> SET exists-key "new-value" XX OK # 設置新值成功 redis 127.0.0.1:6379> GET exists-key "new-value" # NX 或 XX 可以和 EX 或者 PX 組合使用 redis 127.0.0.1:6379> SET key-with-expire-and-NX "hello" EX 10086 NX OK redis 127.0.0.1:6379> GET key-with-expire-and-NX "hello" redis 127.0.0.1:6379> TTL key-with-expire-and-NX (integer) 10063 redis 127.0.0.1:6379> SET key-with-pexpire-and-XX "old value" OK redis 127.0.0.1:6379> SET key-with-pexpire-and-XX "new value" PX 123321 OK redis 127.0.0.1:6379> GET key-with-pexpire-and-XX "new value" redis 127.0.0.1:6379> PTTL key-with-pexpire-and-XX (integer) 112999 # EX 和 PX 可以同時出現,但后面給出的選項會覆蓋前面給出的選項 redis 127.0.0.1:6379> SET key "value" EX 1000 PX 5000000 OK redis 127.0.0.1:6379> TTL key (integer) 4993 # 這是 PX 參數設置的值 redis 127.0.0.1:6379> SET another-key "value" PX 5000000 EX 1000 OK redis 127.0.0.1:6379> TTL another-key (integer) 997 # 這是 EX 參數設置的值
六、使用模式
命令 SET resource-name anystring NX EX max-lock-time 是一種在 Redis 中實現鎖的簡單方法。
客戶端執行以上的命令:
- 如果服務器返回 OK ,那么這個客戶端獲得鎖。
- 如果服務器返回 NIL ,那么客戶端獲取鎖失敗,可以在稍后再重試。
設置的過期時間到達之后,鎖將自動釋放。
可以通過以下修改,讓這個鎖實現更健壯:
- 不使用固定的字符串作為鍵的值,而是設置一個不可猜測(non-guessable)的長隨機字符串,作為口令串(token)。
- 不使用 DEL 命令來釋放鎖,而是發送一個 Lua 腳本,這個腳本只在客戶端傳入的值和鍵的口令串相匹配時,才對鍵進行刪除。
這兩個改動可以防止持有過期鎖的客戶端誤刪現有鎖的情況出現。
以下是一個簡單的解鎖腳本示例:
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 命令來調用。