基本的Redis key的操作都已經(jīng)熟悉了之后,便可以開始針對Redis提供的各種可操作的數(shù)據(jù)結(jié)構(gòu)進行學習和了解。本文依舊是學習Redis的各種命令。
待補充--下述命令的講解及理解;Jedis對應操作;Redis的事務等
首先先學習下Redis String下最常用的Set命令:
String的基本邏輯結(jié)構(gòu)為key->value
SET
SET ${key} ${value}? ? ? ? ? [${exipire seconds}EX|${expire milliseconds}PX]? ? ? ? ?[NX|XX]
將一個key設置一個值,如果對應的key已經(jīng)存在,則覆蓋該key的值;注:操作前一定要check你要操作的key具體類型,或者明確具體類型,若你期望操作的key對應的結(jié)構(gòu)為非String數(shù)據(jù)結(jié)構(gòu),則會直接覆蓋成你新的數(shù)據(jù)結(jié)構(gòu)。因此在key的定義上也要規(guī)避這種重復命名的情況
? ? 時間復雜度O(1),當操作成功時會返回ok(為什么會有失敗呢?因為有下面的幾個可選參數(shù))
? ? 因為我們在Client未開始事務以及腳本操作的情況下,命令個是逐條到達Redis Server的,在兩條命令中間可能會有其他插入的命令,來造成數(shù)據(jù)不安全,不一致的現(xiàn)象,因此,我們不建議設置key值,并設置過期時間通過如下方式:
? ? redis.set(key,value)????
? ? redis.expire(key,seconds)
這里存在兩個問題,1、非原子性操作;2、兩次通信交互,可能存在鏈接等待時間
因此,聰明的Redis設計者提供了如下幾個可選參數(shù):
EX (設置秒過期)設置一個值的時候,同時設置這個key的過期時間,單位是秒,與PX不同時出現(xiàn)
PX (設置毫秒過期)設置一個值的時候,同事設定這個key的過期時間,單位是毫秒,與EX不同時出現(xiàn)
EX/PX在命令中的位置為value后,如:SET mykey "myvalue" 1000 EX
NX (key不存在時設置)設置一個值之前,先檢查對應的key是否存在,若key不存在則設置,若key存在時則不設置返回設置失敗,與XX不同時出現(xiàn)
XX (key存在時設置)設置一個值之前,先檢查對應的key是否存在,若key存在則覆蓋設置,若key不存在則不設置返回設置失敗,與NX不同事出現(xiàn)
NX/XX在命令中的位置為最后位置,如:SET mykey "myvalue" 1000 EX NX
NX一般可利用Redis的單線程原子性原理,來實現(xiàn)分布式鎖,設置成功則持有鎖,設置失敗則未持有鎖,為了避免鎖的無限期存在,需要結(jié)合EX同時使用
XX可以用于分布式強制覆蓋,在部分場景,我們只對存在的數(shù)據(jù)進行二次處理,但是不做數(shù)據(jù)初始化,對于這種場景,我們適用于XX來做覆蓋。
SETNX
SETNX ${key} ${value} 對不存在的key設置一個value,若key已存在則設置失敗,時間復雜度為O(1)
同理 SET ${key} ${value} NX
推薦使用SET命令代替,SET命令可以同步設置PX/EX避免永久鎖的出現(xiàn)
SETEX
SETEX ${key} ${seconds} ${value} 設置key一個value,同步設置其過期時間,時間復雜度O(1)
同理 SET${key} ${value} ${seconds} EX
推薦使用SET命令代替
PSETEX
SETEX的毫秒版本,PSETEX ${key} ${milliseconds} ${value}?
推薦使用SET命令代替
MSET
MSET ${key1} ${value1} [${key2} ${value2} ...${keyn}${valuen}] 批量進行多key的同時賦值,時間復雜度為O(N),N為操作的key數(shù)
這個命令可以理解為多次操作SET,即 MSET key1 "value1" key2 "value2",可以轉(zhuǎn)換為:
SET key1 "value1"
SET key2 "value2"
但是,不推薦這樣使用。
MSET自身是原子性,批量設置非常合適,可以避免網(wǎng)絡異常問題等,適用需要全部成功或全部失敗的情況。
且這里的通訊交互僅一次,可有效避免重復的獲取通訊鏈接的等待時間
批量操作key一般推薦是20個左右一次操作,避免對server進行阻塞,降低redisserver的性能,引起其他需要快速返回的請求
MSETNX
MSETNX?${key1} ${value1} [${key2} ${value2} ...${keyn}${valuen}]? ?批量進行多key的同時賦值,僅所有key均不存在時可操作成功,若有key存在則操作失敗,且全部失敗,具有原子性。時間復雜度為O(N),N為操作的key數(shù)
MSETNX 適用于 多資源條件鎖,當你在執(zhí)行某個操作的時候,你需要多個條件資源,如:
你準備寫一個數(shù)據(jù)合并消費程序,其中由多個程序為你生產(chǎn)數(shù)據(jù),他們使用不同的通道,為了保證通道數(shù)據(jù)傳輸準確,你期望在獲取數(shù)據(jù)的時候不能生產(chǎn),生產(chǎn)數(shù)據(jù)的時候不能讀取,且你期望各生產(chǎn)者能夠最大力度的生產(chǎn)消息,自己可以接受消費后置,則可以推薦使用這個MSETNX命令,可以做到多個資源的同時上鎖,如果某一個key無法上鎖,也不會修改其他可操作的數(shù)據(jù)值,即這是一個等待代價很高的鎖。
但。正如我上面所說的,我們期望每個所都帶有一定的過期時間,使用這個命令,無法保證每個鎖都是帶有過期時間的。
批量操作key一般推薦是20個左右一次操作,避免對server進行阻塞,降低redisserver的性能,引起其他需要快速返回的請求
SETBIT
SETBIT ${key} ${offset} ${value} 在指定偏移量上設置其二進制數(shù),形成一個bitmap;時間復雜度為O(1), offset的取值在0~2^32-1(512MB之內(nèi))
注意的操作offset相當于是高位開始計數(shù),默認按字節(jié)分割(即八位),想要觀察自己設置的結(jié)果,可以用setbit 操作完成后使用get獲取一下
如:setbit mybit 0 1? 生成的結(jié)果為: 1000 0000? ?
setbit mybit 8 1 生成的結(jié)果為: 0000 0000? ?1000 0000
因為SETBIT的操作形式,如果OFFSET設置過大,會在首次操作時,讓Redis生成這個bitmap較久,第二次則不會重新分配空間,因此想要使用請注意offset的大小
該命令可以結(jié)合BITCOUNT,BITOP,GETBIT等用于行為操作統(tǒng)計或分析:
如:統(tǒng)計當日用戶瀏覽某頁面UV,key為當日生成key,offset為uid等。
學好二進制這些東西就能很容易的理解,和找到巧妙的使用場景啦~
SETRANGE
SETRANGE ${key} ${offset} ${value} 在指定offset偏移量上進行value的字符串覆寫,對于無字符串覆蓋部分,Redis使用\x00占位填充
SETBIT是針對偏移量上的二進制進行覆寫來理解的話,SETRANGE就是在指定偏移量上進行字符串的覆寫,同SETBIT,可寫入的內(nèi)存限制在了512MB,即OFFSET限定在了0~2^29-1(字符默認占用1個字節(jié),即2^3(8bit))
時間復雜度上為O(M)M為字符串長度(據(jù)說在小字符串情況下平攤復雜度是O(1))待讀源碼
返回值是修改后的字符串長度
GETSET
GETSET ${key} ${value}? 覆寫一個key的value,并返回舊值,若key不是字符型,則拋錯,時間復雜度O(1)
返回值為舊值,當key不存在時返回nil
這個命令是原子性獲取原值的命令,可以用于很多,我們做替換型操作的命令,如搶奪,接力等。
也可用于計數(shù)歸零操作,方便記錄歸零前數(shù)據(jù)。
接下來是與SET對應的GET命令:
GET
GET ${key} 獲取key對應的value,若key對應的value結(jié)構(gòu)非String類型會返回一個錯誤,時間復雜度為O(1)
返回值為:key對應的String值,若不存在則為nil,若結(jié)構(gòu)不是String則返回一個錯誤
MGET
MGET ${key1} [${key2}...${keyn}] 同時獲取多個key對應的value,返回一個列表,時間復雜度為O(N) N為key的數(shù)量
注意:這個命令不會報錯,哪怕你的key對應的結(jié)構(gòu)不是string,也不會報錯,只會在對應的位置返回nil
因為返回值為一個列表,因此在獲取結(jié)構(gòu)時,務必注意保存結(jié)構(gòu)的順序,根據(jù)順序匹配結(jié)果
另外,多key獲取數(shù)據(jù)時,不推薦使用 get key1? get key2 ...多部操作,而是推薦mget操作,減少命令操作對鏈接獲取的等待時間
批量操作key一般推薦是20個左右一次操作,避免對server進行阻塞,降低redisserver的性能,引起其他需要快速返回的請求
GETBIT
GETBIT ${key} ${offset} 主要針對 SETBIT的存儲結(jié)果進行查詢,獲取偏移量在offset位置的二進制數(shù)據(jù),時間復雜度O(1),返回值 0或1,若類型非String,則返回一個錯誤
當利用SETBIT生成一個BITMAP的時候,GETBIT是很好的獲取對應位數(shù)據(jù)的命令
GETRANGE
GETRANGE ${key} ${start}${end} 獲取key對應字符串的start 偏移量到end偏移量之間的字符串,時間復雜度O(N),N為待返回的字符串長度
start 為開始字符,從左開始計數(shù)為0,當為負數(shù)時,表示從右開始計數(shù)的第n個,如-1,表示右側(cè)第一個字符
end同理,為結(jié)束字符
舉例說明:
字符串:set myrange? "0123456789abcdef"
getrange myrange 0 10 ------>"0123456789a"
getrange myrange 10 15?------>"abcdef"
getrange myrange 12 20?------>"cdef"
getrange myrange 0 -1?------>"0123456789abcdef"
getrange myrange 0 -2?------>"0123456789abcde"
getrange myrange -1 -2?------>""
接下來是一些用于疊加器:
INCRBY
? INCRBY ${key} ${increment}? 將key對應的數(shù)值按increment的幅度增加,increment必須是一個整數(shù)(可以為負數(shù),負數(shù)則較為類似一個decr),如果key不存在則先初始化為0,然后執(zhí)行incrby操作,即,若key: myincr不存在,執(zhí)行 INCRBY myincr 10 的執(zhí)行結(jié)果為10,時間復雜度是O(1),返回值就是執(zhí)行incrby之后的key對應的結(jié)果,當key對應的結(jié)構(gòu)不是String,且不是integer類型的數(shù)據(jù)時,會提示一個錯誤(即負數(shù)也是可以的)。注:該命令的值限制在-2^63~2^63-1(即64bit內(nèi))
該命令主要用于計數(shù),分布式任務執(zhí)行同步,累計步幅,和expire結(jié)合使用可以做分時限流,再結(jié)合setrange甚至可以完成統(tǒng)計并記錄到時間序列上
INCR
INCR ${key} 將key對應的數(shù)值按增幅為1的幅度增加,如果key不存在則先初始化為0,然后再執(zhí)行incr操作,實際上等于incrby ${key} 1,時間復雜度是O(1),返回值就是執(zhí)行incr之后的key對應的結(jié)果,當key對應的結(jié)構(gòu)不是String,且不是integer類型的數(shù)據(jù)時,會提示一個錯誤(即負數(shù)也是可以的)。注:該命令的值限制在-2^63~2^63-1(即64bit內(nèi))
INCRBYFLOAT
? INCRBY ${key} ${increment} 將key對應的述職按increment的幅度增加,increment必須是一個可以轉(zhuǎn)換為雙精度浮點數(shù)的數(shù)值(可以為負數(shù)),如果key不存在則先初始化為0,然后執(zhí)行incrbyfloat操作,時間復雜度是O(1),返回值就是執(zhí)行incrbyfloat之后的key對應的結(jié)果,當key對應的結(jié)構(gòu)不是String,且不是數(shù)值類型的數(shù)據(jù)時,會提示一個錯誤。注:命令的小數(shù)要注意小數(shù)點最多保留小數(shù)點后17位
遞減器:
DECRBY
DECRBY ${key} ${increment}? 將key對應的數(shù)值按increment的幅度減少,increment必須是一個整數(shù)(可以為負數(shù),負數(shù)則較為類似一個incr),如果key不存在則先初始化為0,然后執(zhí)行decrby操作,即,若key: mydecr不存在,執(zhí)行 DECRBY mydecr 10 的執(zhí)行結(jié)果為-10,時間復雜度是O(1),返回值就是執(zhí)行decrby之后的key對應的結(jié)果,當key對應的結(jié)構(gòu)不是String,且不是integer類型的數(shù)據(jù)時,會提示一個錯誤(即負數(shù)也是可以的)。注:該命令的值限制在-2^63~2^63-1(即64bit內(nèi))
可用做最大重試次數(shù),或最大次數(shù)限定
DECR
DECR ${key} 將key對應的數(shù)值按增幅為1的幅度減少,如果key不存在則先初始化為0,然后再執(zhí)行decr操作,實際上等于decrby ${key} 1,時間復雜度是O(1),返回值就是執(zhí)行incr之后的key對應的結(jié)果,當key對應的結(jié)構(gòu)不是String,且不是integer類型的數(shù)據(jù)時,會提示一個錯誤(即負數(shù)也是可以的)。注:該命令的值限制在-2^63~2^63-1(即64bit內(nèi))
字符長度:
STRLEN
STRLEN ${key} 返回key對應字符串的字符長度,時間復雜度是O(1),返回值為字符串的字符長度,就算是數(shù)值也是按字符串方式獲取其長度,若key不存在,則返回0,若key不是字符串,則返回一個錯。(Redis底層使用SDS結(jié)構(gòu),內(nèi)置字符長度,因此時間復雜度為O(1))
字符拼接:
APPEND
APPEND ${key} ${value} 在key對應的字符串后面追加value字符串,并返回其追加后的字符串長度。時間復雜度平攤O(1)(原因待學習)。返回值:拼接后的字符串的長度。若key不存在則相當于set命令,若key對應的值非String類型,則返回一個錯誤。
位運算:
BITCOUNT
BITCOUNT ${key} [${start}] [${end}] 獲取start到end之間位之和,時間復雜度O(N),N為待返回的字符串長度
start 為開始字符,從左開始計數(shù)為0,當為負數(shù)時,表示從右開始計數(shù)的第n個,如-1,表示右側(cè)第一個字符
end同理,為結(jié)束字符
BITOP
BITOP ${OP} ${dest} ${key1} [${key2}...${keyn}] 將key1到keyn 這些key對應的位內(nèi)容進行OP操作,并將操作結(jié)果保存至以dest為key的結(jié)果內(nèi),同時返回操作結(jié)果的長度,時間復雜度為O(N),對大型矩陣的操作要避免在master操作,避免阻塞
OP 包含: AND (并) OR(或)XOR(異或)NOT(非)
注:非情況,僅支持一個key
OK
OK
大家讀完一遍之后,發(fā)現(xiàn),哎呀,咋感覺這么亂呢。
其實是上面,只是按照命令操作類型進行了排序,如果還有一些困惑的同學,可以按照下述順序再進行一次學習:
對于String下面的更多類型來分解:
數(shù)值類型:(注意除了incr,decr這類按照數(shù)值進行操作,有數(shù)值依賴的操作外,其他均將對數(shù)值當字符操作)
初始化、覆蓋可以使用:SET;
批量初始化、覆蓋可以使用:MSET;
獲取可以使用:GET;
批量獲取可以使用:MGET;
設置過期可以使用EXPIRE;
原子性簡單SET & EXPIRE 可以使用SETEX,當然也可以使用 SET EX;
設置毫秒級過期可以使用PEXPIRE;
原子性簡單SET & PEXPIRE 可以使用PSETEX,當然也可以使用 SET PX;
設置前檢查值是否存在可以使用:EXISTS;
原子性簡單EXISTS & SET 可以使用 SETNX, 淡然也可以使用 SET NX;
同時對多個key設置SETNX,可以使用MSETNX;
如果希望SETNX + SETEX 必須使用 SET EX NX;
增加整型數(shù)字可以使用:INCR、有步幅設置的可以使用:INCRBY;
增加浮點型數(shù)字可以使用:INCRBYFLOAT;
減少整型數(shù)字可以使用:DECR、有步幅設置的可以使用:DECRBY;
如果希望設置一個值前,先獲取下之前的值,可以 使用GETSET;
位運算,bit類型:(注意bit類型的操作也可被其他操作覆蓋修改,要注意避免沖突使用)
設置某個位上的值,可以使用SETBIT;
對應獲取某個位上的值,可以使用GETBIT;
獲取指定范圍內(nèi),位值和,可以使用BITCOUNT;
如果希望進行常規(guī)的位運算,可以使用BITOP;
上述內(nèi)容,除了強制要求數(shù)值類型的操作外;均可操作這類位運算的結(jié)果;
純字符類型:
初始化、覆蓋可以使用:SET;
批量初始化、覆蓋可以使用:MSET;
獲取可以使用:GET;
批量獲取可以使用:MGET;
設置過期可以使用EXPIRE;
原子性簡單SET & EXPIRE 可以使用SETEX,當然也可以使用 SET EX;
設置毫秒級過期可以使用PEXPIRE;
原子性簡單SET & PEXPIRE 可以使用PSETEX,當然也可以使用 SET PX;
設置前檢查值是否存在可以使用:EXISTS;
原子性簡單EXISTS & SET 可以使用 SETNX, 淡然也可以使用 SET NX;
同時對多個key設置SETNX,可以使用MSETNX;
如果希望SETNX + SETEX 必須使用 SET EX NX;
如果希望設置一個值前,先獲取下之前的值,可以 使用GETSET;
設置字符串內(nèi)范圍值,可以使用SETRANGE;
獲取字符串內(nèi)范圍值,可以使用GETRANGE;
字符串拼接覆蓋,可以使用APPEND;
高效獲取字符長度,可以使用STRLEN;
如果只是常規(guī)操作字符串,那么就記好:
SET 默認不過期,后追EXPIRE操作非原子性,使用SET EX(PX)更省心
想用Redis做鎖,用好SETNX,后追EXPIRE操作非原子性,使用SET EX(PX)NX更省心
獲取數(shù)據(jù)用GET,不是必須提前用EXISTS
循環(huán)操作SET、GET浪費Client的網(wǎng)絡和鏈接,可以用MSET、MGET減少鏈接次數(shù)(注意避免過大操作)
其他類型根據(jù)情況可以巧用~
掰掰~