Strings是Redis支持的最簡單數(shù)據(jù)類型粉私,以下按照SET/GET
帅掘、INCR/DECR
、BIT
3種分類介紹字符串格式支持的命令康铭。
SET/GET類???
最簡單的SET/GET操作:
SET mykey "hello" => "OK"
GET mykey => "hello"
SET操作會在Redis中創(chuàng)建一個值為hello的key(mykey)。如果key已經(jīng)存在赌髓,它的值將會被覆蓋从藤。GET操作用于獲取mykey對應(yīng)的值hello。
SET操作可以附加一些參數(shù):
SET mykey "hello" EX 10
EX 10
會導(dǎo)致mykey在10秒后失效锁蠕,超過10秒后使用GET操作會得到nil:
GET mykey => "(nil)"
PX 10000
與EX 10
功?能相似夷野,只是時(shí)間單位變成了毫秒。
SET mykey "hello" NX => "OK"
SET mykey "hello" XX => "OK"
NX
的語義為當(dāng)key不存在時(shí)才設(shè)置匿沛,XX
的語義為當(dāng)key存在才設(shè)置扫责,失敗時(shí)會返回nil。
模式-通過Redis實(shí)現(xiàn)簡單鎖
SET lock "anyString" NX EX 10
通過上面的命令逃呼,可以借助Redis實(shí)現(xiàn)鎖的功能鳖孤。當(dāng)命令返回OK代表客戶端成功獲取到鎖;當(dāng)超過10秒后抡笼,鎖會自動釋放苏揣;客戶端也可以通過DEL
命令主動釋放鎖。
簡單鎖會存在兩個問題:
1推姻、key只有一個平匈;
2、client1獲取到鎖后,client2可以通過DEL命令釋放鎖增炭;改進(jìn):
1忍燥、key通過隨機(jī)算法生成字符串;
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
具有相同功能赔嚎,但返回值有些區(qū)別膘盖。
MSETNX key1 "hello" key2 "world" => "(integer) 1"
MSETNX key1 "hello" key3 "test" => "(integer) 0"
GET key3 => "(nil)"
批量版的SETNX,只能全部寫入成功或全部失敗尽狠。
另一種鎖實(shí)現(xiàn)
SETNX lock.foo <current Unix time + lock timeout + 1>
假設(shè)有client1衔憨、client2、client3在競爭鎖袄膏,只有一個client的SETNX
操作會返回1践图,代表當(dāng)前client獲取到鎖。client后續(xù)可以通過DEL操作釋放鎖沉馆。
死鎖問題處理:
1码党、client1獲取到鎖后crash了;
2斥黑、client2通過SETNX操作嘗試獲取鎖揖盘,但是鎖仍然被client1持有,所有redis返回0锌奴;
3兽狭、client2通過GET操作,獲取lock.foo值中保存的時(shí)間戳鹿蜀,與當(dāng)前時(shí)間比較箕慧,發(fā)現(xiàn)鎖已經(jīng)超時(shí);
4茴恰、client2發(fā)送GETSET lock.foo <current Unix timestamp + lock timeout + 1>
操作颠焦,并檢查返回值是否依舊是超時(shí)的時(shí)間,如果超時(shí)說明client2已經(jīng)獲取到了鎖往枣;
5伐庭、如果不是超時(shí)粉渠,說明有另外的client已經(jīng)修改了時(shí)間戳,client2會從步驟2重新嘗試獲取鎖圾另;
其他
GETSET
設(shè)置新值霸株,返回老值;
SETRANGE/GETRANGE
設(shè)置/獲取字符串中的一段集乔;
STRLEN
獲取字符串長度淳衙;
INCR/DECR類???
遞增操作:INCR
INCRBY
INCRBYFLOAT
遞減操作:DECR
DECRBY
只有
INCRBYFLOAT
而沒有DECRBYFLOAT
,但是可以通過用負(fù)數(shù)做參數(shù)實(shí)現(xiàn)同樣的效果饺著。
BIT類
Bitmap,一串連續(xù)的二進(jìn)制數(shù)字肠牲,可以在極少的空間內(nèi)進(jìn)行統(tǒng)計(jì)計(jì)算幼衰。Redis提供了一組的Bitmap操作。
SETBIT bitkey 10 1 => "(integer) 0"
GETBIT bitkey 10 => "(integer) 1"
GETBIT bitkey 1 => "(integer) 0"
SETBIT的值只能是0或1缀雳。當(dāng)key不存在時(shí)會創(chuàng)建一個新的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"
統(tǒng)計(jì)bitkey中有多少位被置為1。
模式-利用bitmap統(tǒng)計(jì)用戶訪問歷史
SETBIT user:yingzong 0 1 => "(integer) 0"
offset 0代表網(wǎng)站上線的第一天深碱,每天遞增1腹鹉。需要時(shí)可以通過BITCOUNT命令統(tǒng)計(jì)bitmap中被置為1的位數(shù),代表用戶訪問天數(shù)敷硅。
便利操作BITFIELD
Redis3.2提供了BITFIELD操作功咒,可以在一條指令中執(zhí)行多個分段的Bitmap操作。
BITFIELD bitkey SET i4 0 5 => "1) (integer) 0"
用bitkey的值绞蹦,0-3位保存有符號整數(shù)值5力奋。i4代表4位有符號整數(shù),u4代表4位無符號整數(shù)幽七。
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的整數(shù),值為127澡屡,遞增1會導(dǎo)致值變?yōu)?128;
SAT
一個i8的整數(shù)猿挚,值為120,遞增10會導(dǎo)致值變?yōu)?27;
FAIL
發(fā)生溢出時(shí)操作失斉膊洹亭饵;
BITFIELD bits SET i8 0 127 OVERFLOW WRAP INCRBY i8 0 1
=> "1) (integer) 0"
=> "2) (integer) -128"
其他操作
BITPOS
返回第一個被設(shè)置為0或1的位置。
SETBIT pos 10 1 => "(integer) 0"
BITPOS pos 1 => "(integer) 10"
BITPOS的最后兩個參數(shù)是byte梁厉,如果執(zhí)行以下命令:
BITPOS pos 0 1 => "(integer) 8"
因?yàn)橄拗屏藦牡谝粋€字節(jié)開始(0計(jì)數(shù))辜羊,所以第一個為0的位的offset是8踏兜。
BITOP
在多個key之間執(zhí)行與、或八秃、異或碱妆、非等邏輯操作。