1.增
set key value :
如果key已經持有其他值,SET就覆寫舊值,無視類型。
返回值:
總是返回OK,因爲SET不可能失敗。setnx key value :
如果key已經存在了,就不做任何操作。
返回:
1或者0
setex key seconds value
將值value關聯到key,並將key的生存時間設爲seconds(以秒爲單位)。如果key存在,就覆寫舊值。
返回值:
設置成功時返回OK。
當seconds參數不合法時,返回一個錯誤。
mset key value [key value ....]
一個原子操作,新值覆蓋舊值
返回值: 總是返回OK(因爲MSET不可能失敗)msetnx 是原子操作,如果一個key不存在,就全部不執行
返回值:1或者0
2.刪
del key
3.改
setrange key offset value:
把key的第offset個字符開始,設置爲value,如果key不存在,就創建
返回值: 被SETRANGE修改之後,字符串的長度。
append key value
在key的基礎上,追加value,如果key不存在,就和set 是一樣的
返回值: 追加value之後,key中字符串的長度。一個原子操作,新值覆蓋舊值
返回值: 總是返回OK(因爲MSET不可能失敗)getset key value:
設置新值,返回key的舊值。
如果key不存在,返回nildecr key :
將key的值減一。
如果可以不存在,就以0減一,如果key的value爲str,就報錯,
decrby key decrement :減去decrement
如果key不存在,按照0開始算。如果key的value 是字符串,則報錯。
incr key
incrby key increment
同上
4.查
mget key [key....]
如果其中一個key 不存在,則該key返回nil
getrange key start end
key 不存在 返回“” ,如果超出字符串的長度,就返回字符串本身
strlen key :
不存在key,返回0
exists key:
不存在key,返回0
知識點:
設計模式(Design pattern): 將SETNX用於加鎖(locking)
SETNX可以用作加鎖原語(locking primitive)。比如說,要對關鍵字(key)foo加鎖,客戶端可以嘗試以下方式:
SETNX lock.foo <current Unix time + lock timeout + 1>
如果SETNX返回1,說明客戶端已經獲得了鎖,key設置的unix時間則指定了鎖失效的時間。之後客戶端可以通過DEL lock.foo來釋放鎖。
如果SETNX返回0,說明key已經被其他客戶端上鎖了。如果鎖是非阻塞(non blocking lock)的,我們可以選擇返回調用,或者進入一個重試循環,直到成功獲得鎖或重試超時(timeout)。
處理死鎖(deadlock)
上面的鎖算法有一個問題:如果因爲客戶端失敗、崩潰或其他原因導致沒有辦法釋放鎖的話,怎麼辦?
這種狀況可以通過檢測發現——因爲上鎖的key保存的是unix時間戳,假如key值的時間戳小於當前的時間戳,表示鎖已經不再有效。
但是,當有多個客戶端同時檢測一個鎖是否過期並嘗試釋放它的時候,我們不能簡單粗暴地刪除死鎖的key,再用SETNX上鎖,因爲這時競爭條件(race condition)已經形成了:
- C1和C2讀取lock.foo並檢查時間戳,SETNX都返回0,因爲它已經被C3鎖上了,但C3在上鎖之後就崩潰(crashed)了。
- C1向lock.foo發送DEL命令。
- C1向lock.foo發送SETNX併成功。
- C2向lock.foo發送DEL命令。
- C2向lock.foo發送SETNX併成功。
- 出錯:因爲競爭條件的關係,C1和C2兩個都獲得了鎖。
幸好,以下算法可以避免以上問題。來看看我們聰明的C4客戶端怎麼辦:
- C4向lock.foo發送SETNX命令。
- 因爲崩潰掉的C3還鎖着lock.foo,所以Redis向C4返回0。
- C4向lock.foo發送GET命令,查看lock.foo的鎖是否過期。如果不,則休眠(sleep)一段時間,並在之後重試。
- 另一方面,如果lock.foo內的unix時間戳比當前時間戳老,C4執行以下命令:
GETSET lock.foo <current Unix timestamp + lock timeout + 1>
- 因爲GETSET的作用,C4可以檢查看GETSET的返回值,確定lock.foo之前儲存的舊值仍是那個過期時間戳,如果是的話,那麼C4獲得鎖。
- 如果其他客戶端,比如C5,比C4更快地執行了GETSET操作並獲得鎖,那麼C4的GETSET操作返回的就是一個未過期的時間戳(C5設置的時間戳)。C4只好從第一步開始重試。