Strings是Redis支持的最簡單數據類型,以下按照SET/GET
、INCR/DECR
、BIT
3種分類介紹字符串格式支持的命令。
SET/GET類???
最簡單的SET/GET操作:
SET mykey "hello" => "OK"
GET mykey => "hello"
SET操作會在Redis中創建一個值為hello的key(mykey)。如果key已經存在,它的值將會被覆蓋。GET操作用于獲取mykey對應的值hello。
SET操作可以附加一些參數:
SET mykey "hello" EX 10
EX 10
會導致mykey在10秒后失效,超過10秒后使用GET操作會得到nil:
GET mykey => "(nil)"
PX 10000
與EX 10
功?能相似,只是時間單位變成了毫秒。
SET mykey "hello" NX => "OK"
SET mykey "hello" XX => "OK"
NX
的語義為當key不存在時才設置,XX
的語義為當key存在才設置,失敗時會返回nil。
模式-通過Redis實現簡單鎖
SET lock "anyString" NX EX 10
通過上面的命令,可以借助Redis實現鎖的功能。當命令返回OK代表客戶端成功獲取到鎖;當超過10秒后,鎖會自動釋放;客戶端也可以通過DEL
命令主動釋放鎖。
簡單鎖會存在兩個問題:
1、key只有一個;
2、client1獲取到鎖后,client2可以通過DEL命令釋放鎖;改進:
1、key通過隨機算法生成字符串;
2、DEL操作前,還需要加入Value的比較,再做DEL操作;引用一段Redis文檔中的代碼:
if redis.call("get",KEYS[1]) == ARGV[1]
then
return redis.call("del",KEYS[1])
else
return 0
end
批量SET/GET
MSET key1 "Hello" key2 "World" => "OK"
MGET key1 key2
=> 1) "Hello"
=> 2) "World"
批量版SET/GET操作,不過多介紹了。
SET的變種兄弟們
SETEX mykey 10 "hello" => "OK"
與SET mykey "hello" EX 10
具有相同功能。另還有PSETEX
命令,單位為毫秒。
SETNX mykey "hello" => "(integer) 1"
SETNX mykey "hello" => "(integer) 0"
與SET mykey "hello" NX
具有相同功能,但返回值有些區別。
MSETNX key1 "hello" key2 "world" => "(integer) 1"
MSETNX key1 "hello" key3 "test" => "(integer) 0"
GET key3 => "(nil)"
批量版的SETNX,只能全部寫入成功或全部失敗。
另一種鎖實現
SETNX lock.foo <current Unix time + lock timeout + 1>
假設有client1、client2、client3在競爭鎖,只有一個client的SETNX
操作會返回1,代表當前client獲取到鎖。client后續可以通過DEL操作釋放鎖。
死鎖問題處理:
1、client1獲取到鎖后crash了;
2、client2通過SETNX操作嘗試獲取鎖,但是鎖仍然被client1持有,所有redis返回0;
3、client2通過GET操作,獲取lock.foo值中保存的時間戳,與當前時間比較,發現鎖已經超時;
4、client2發送GETSET lock.foo <current Unix timestamp + lock timeout + 1>
操作,并檢查返回值是否依舊是超時的時間,如果超時說明client2已經獲取到了鎖;
5、如果不是超時,說明有另外的client已經修改了時間戳,client2會從步驟2重新嘗試獲取鎖;
其他
GETSET
設置新值,返回老值;
SETRANGE/GETRANGE
設置/獲取字符串中的一段;
STRLEN
獲取字符串長度;
INCR/DECR類???
遞增操作:INCR
INCRBY
INCRBYFLOAT
遞減操作:DECR
DECRBY
只有
INCRBYFLOAT
而沒有DECRBYFLOAT
,但是可以通過用負數做參數實現同樣的效果。
BIT類
Bitmap,一串連續的二進制數字,可以在極少的空間內進行統計計算。Redis提供了一組的Bitmap操作。
SETBIT bitkey 10 1 => "(integer) 0"
GETBIT bitkey 10 => "(integer) 1"
GETBIT bitkey 1 => "(integer) 0"
SETBIT的值只能是0或1。當key不存在時會創建一個新的string值,Redis會確保string足夠保存指定offset的bit。offset的范圍從0到2^32-1。SETBIT的返回值是指定offset之前保存的bit。
BITCOUNT bitkey => "(integer) 1"
BITSET bitkey 0 1 => "(integer) 0"
BITCOUNT bitkey => "(integer) 2"
統計bitkey中有多少位被置為1。
模式-利用bitmap統計用戶訪問歷史
SETBIT user:yingzong 0 1 => "(integer) 0"
offset 0代表網站上線的第一天,每天遞增1。需要時可以通過BITCOUNT命令統計bitmap中被置為1的位數,代表用戶訪問天數。
便利操作BITFIELD
Redis3.2提供了BITFIELD操作,可以在一條指令中執行多個分段的Bitmap操作。
BITFIELD bitkey SET i4 0 5 => "1) (integer) 0"
用bitkey的值,0-3位保存有符號整數值5。i4代表4位有符號整數,u4代表4位無符號整數。
BITFIELD bitkey GET i4 => "1) (integer) 5"
獲取剛才保存的值。BITFIELD命令可以組合使用:
BITFIELD bitkey GET i4 0 SET u4 4 6 INCRBY u4 4 1
=> "1) (integer) 5"
=> "2) (integer) 0"
=> "3) (integer) 7"
另外BITFIELD還提供了三種溢出策略:
WRAP
一個i8的整數,值為127,遞增1會導致值變為-128;
SAT
一個i8的整數,值為120,遞增10會導致值變為127;
FAIL
發生溢出時操作失敗;
BITFIELD bits SET i8 0 127 OVERFLOW WRAP INCRBY i8 0 1
=> "1) (integer) 0"
=> "2) (integer) -128"
其他操作
BITPOS
返回第一個被設置為0或1的位置。
SETBIT pos 10 1 => "(integer) 0"
BITPOS pos 1 => "(integer) 10"
BITPOS的最后兩個參數是byte,如果執行以下命令:
BITPOS pos 0 1 => "(integer) 8"
因為限制了從第一個字節開始(0計數),所以第一個為0的位的offset是8。
BITOP
在多個key之間執行與、或、異或、非等邏輯操作。