鄭州網(wǎng)站建設(shè)找智巢2345導(dǎo)航網(wǎng)址
初識(shí)Redis緩存
Redis緩存:
實(shí)際開發(fā)中經(jīng)常使用Redis作為緩存數(shù)據(jù)庫(kù),從而提高數(shù)據(jù)存取效率,減輕后端數(shù)據(jù)庫(kù)的壓力。
可以將經(jīng)常被查詢的數(shù)據(jù)緩存起來,比如熱點(diǎn)數(shù)據(jù),這樣當(dāng)用戶來訪問的時(shí)候,就不需要到MySQL中去查詢了,而是直接獲取Redis中的緩存數(shù)據(jù)。
Redis是鍵值對(duì)類型的數(shù)據(jù)庫(kù),在設(shè)計(jì)數(shù)據(jù)時(shí)都要指定key和value。
例如某查詢系統(tǒng)可以根據(jù)提供的網(wǎng)站名稱返回相應(yīng)的網(wǎng)址,因?yàn)椴樵兊南到y(tǒng)的并發(fā)量較高,此時(shí)可以將上述的對(duì)應(yīng)關(guān)系通過Redis緩存到內(nèi)存中。
設(shè)置網(wǎng)站名稱baidu到網(wǎng)址http://www.baidu.com的對(duì)應(yīng)關(guān)系:名稱作為key,網(wǎng)址作為value
取出緩存:用戶輸入名稱,數(shù)據(jù)庫(kù)就可以把對(duì)應(yīng)網(wǎng)址取出來了
設(shè)置緩存的時(shí)間:
實(shí)際項(xiàng)目里一般需要同時(shí)設(shè)置數(shù)據(jù)的生存時(shí)間。如果不設(shè)置,那么內(nèi)存里的數(shù)據(jù)會(huì)越積越多,最終造成內(nèi)存溢出。
可以在命令后通過ex或px參數(shù)設(shè)置該對(duì)象的生存時(shí)間,其中ex的時(shí)間單位是秒,px的時(shí)間單位是毫秒,如:
設(shè)置了val1對(duì)象的生存時(shí)間是2秒,當(dāng)過了對(duì)應(yīng)的時(shí)間用get命令去獲取對(duì)象的值時(shí),只能得到表示空的null值。
Redis數(shù)據(jù)類型
Redis為了存儲(chǔ)不同類型的數(shù)據(jù),提供了五種常用數(shù)據(jù)類型
string? (字符串)
hash? (哈希散列)
list? (列表)
set? (集合)
zset? (sorted set:有序集合)
注意此處的數(shù)據(jù)類型指的是Value(值)的數(shù)據(jù)類型,而非key。
基本數(shù)據(jù)類型String
SDS:
字符串是Redis里最基本的數(shù)據(jù)類型,Redis使用標(biāo)準(zhǔn)C語言編寫,但在存儲(chǔ)字符時(shí),Redis并未使用C語言的字符類型。
而是自定義了一個(gè)屬于特殊結(jié)構(gòu)SDS(Simple Dynamic String)即簡(jiǎn)單動(dòng)態(tài)字符串)?!究梢岳斫鉃橛肅的結(jié)構(gòu)體實(shí)現(xiàn)了一個(gè)String類型】
SDS是一個(gè)可以修改的內(nèi)部結(jié)構(gòu),非常類似于Java的ArrayList。
SDS的結(jié)構(gòu)定義如下:
String類型的空間分配方式:
string采用了預(yù)先分配冗余空間的方式來減少內(nèi)存的頻繁分配,如下圖所示:
(總體空間即上圖char buf[]的空間?)
Redis每次給string分配的空間都要大于字符串實(shí)際占用的空間,這樣就在一定程度上提升了Redis string存儲(chǔ)的效率,比如當(dāng)字符串長(zhǎng)度變大時(shí),無需再重新申請(qǐng)內(nèi)存空間。
當(dāng)字符串所占空間小于1MB時(shí),Redis對(duì)字符串存儲(chǔ)空間的擴(kuò)容是以成倍的方式增加的;而當(dāng)所占空間超過1MB時(shí),每次擴(kuò)容只增加1MB。Redis字符串允許的最大值字節(jié)數(shù)是512MB。
String類型的使用:
字符串是Redis里最基本的數(shù)據(jù)類型。
可以使用set命令設(shè)置字符串類型數(shù)據(jù),具體語法如下:
set key value [EX seconds|PX milliseconds] [NX|XX] [KEEPTTL]
key和value分別表示待設(shè)置字符串的鍵和值,如果對(duì)應(yīng)的key里已經(jīng)有值,那么再次執(zhí)行set命令時(shí)會(huì)進(jìn)行覆蓋。value就是String類型。[]中為可選內(nèi)容
通過EX和PX參數(shù)可以指定該變量的生存時(shí)間,在大多數(shù)場(chǎng)景里,應(yīng)該合理設(shè)置對(duì)應(yīng)的生存時(shí)間,否則可能會(huì)導(dǎo)致內(nèi)存溢出的問題。
NX參數(shù)表示當(dāng)key不存在時(shí)才進(jìn)行設(shè)置值的操作,如果key存在,那么該命令執(zhí)行;XX參數(shù)表示當(dāng)key存在時(shí)才進(jìn)行操作。
KEEPTTL是Redis6.0的新特性,是指"保留生存時(shí)間”,既重復(fù)set時(shí),保留值的過期時(shí)間。
設(shè)置以后,可以通過get key的方式讀取對(duì)應(yīng)key的字符串變量,具體示例:
設(shè)置獲取單個(gè)字符串:
緩存員工號(hào)002、姓名Tom"的數(shù)據(jù):
設(shè)置獲取多個(gè)字符串:
mset和mget命令分別能同時(shí)設(shè)置和獲取多個(gè)字符串。
其中,mset命令的語法:mset key value [key value...]
mget命令的語法:mget key [key...]
mset和mget命令不包含NX、XX、PX和EX等參數(shù)。
示例:
ttl =-1 代表永久有效
對(duì)值進(jìn)行增量和減量操作:
通過incr key命令能對(duì)key所對(duì)應(yīng)的數(shù)字類型值進(jìn)行加1操作,如果k不存在,默認(rèn)在0的基礎(chǔ)上+1
通過decr key命令能對(duì)key所對(duì)應(yīng)的值進(jìn)行減1操作,如果k不存在,默認(rèn)在0的基礎(chǔ)上-1
通過incrby key increment命令能對(duì)key對(duì)應(yīng)的值進(jìn)行加lincrement的操作
通過decrby by decrement命令能對(duì)key對(duì)應(yīng)的值進(jìn)行減decrement的操作
incr和decr命令作用在字符類型上,會(huì)出錯(cuò)
運(yùn)行上述命令時(shí),需要確保key對(duì)應(yīng)的值是數(shù)字類型,否側(cè)會(huì)報(bào)錯(cuò)。在實(shí)際項(xiàng)目里,上述命令一般會(huì)用在統(tǒng)計(jì)流量和控制并發(fā)的場(chǎng)景中
通過getset命令設(shè)置新值:
getset key value
如果key對(duì)應(yīng)的值存在,則會(huì)用value覆蓋舊值,同時(shí)返回舊值(set可以覆蓋但不會(huì)返回舊值)
如果key對(duì)應(yīng)的值不存在,也會(huì)設(shè)值,但會(huì)返回null
基本數(shù)據(jù)類型Hash
Hash類型:
Redis hash(哈希散列)是由字符類型的field(字段)和value組成的哈希映射表結(jié)構(gòu)(也稱散列表)
【redis的鍵值對(duì)映射則指的是整體數(shù)據(jù)】
hash類型中,field與value一一對(duì)應(yīng),且不允許重復(fù)。
Redis hash特別適合于存儲(chǔ)對(duì)象。一個(gè)filed/value可以看做是表格中一條數(shù)據(jù)記錄;而一個(gè)key可以對(duì)應(yīng)多條數(shù)據(jù)(多個(gè)字段和value的組合)。
當(dāng)hash類型移除最后一個(gè)元素后,該存儲(chǔ)結(jié)構(gòu)就會(huì)被自動(dòng)刪除,其占用內(nèi)存也會(huì)被系統(tǒng)回收。
Hash類型底層存儲(chǔ)結(jié)構(gòu)的實(shí)現(xiàn)方式(2種):
第一種,當(dāng)存儲(chǔ)的數(shù)據(jù)量較少時(shí),hash采用ziplist(壓縮列表,內(nèi)存中一塊連續(xù)的存儲(chǔ)空間)作為底層存儲(chǔ)結(jié)構(gòu),此時(shí)要求符合以下兩個(gè)條件:
(1)哈希對(duì)象保存的所有鍵值對(duì)(鍵和值)的字符串長(zhǎng)度總和小于64個(gè)字節(jié)。
(2)哈希對(duì)象保存的鍵值對(duì)數(shù)量要小于512個(gè)。
當(dāng)無法滿足上述條件時(shí),hash就會(huì)采用第二種方式來存儲(chǔ)數(shù)據(jù):
也就是dict(字典結(jié)構(gòu))該結(jié)構(gòu)類似于Java的HashMap,是一個(gè)無序的字典,并采用了數(shù)組和鏈表相結(jié)合的方式存儲(chǔ)數(shù)據(jù)。
在Redis中,dict是基于哈希表算法實(shí)現(xiàn)的,因此其查找性能非常高效,其時(shí)間復(fù)雜度為O(1)。
哈希表:
哈希表又稱散列表,其初衷是將數(shù)據(jù)映射到數(shù)組中的某個(gè)位置上, 這樣就能夠通過數(shù)組下標(biāo)來訪問該數(shù)據(jù),從而提高數(shù)組的查詢效率。
現(xiàn)在有1/5/8/ 三個(gè)數(shù)字,你需要把這三個(gè)數(shù)字映射到數(shù)組中,由于哈希表規(guī)定必須使用下標(biāo)來訪問數(shù)據(jù),因此你需要構(gòu)建一個(gè)0到8的數(shù)組
普通查找:把待查找的數(shù)字,在相應(yīng)的下標(biāo)數(shù)組上標(biāo)記出來,它們之間一一對(duì)應(yīng)。雖然這樣能查,但很浪費(fèi)存儲(chǔ)空間,并且查找效率也不高。
如果采用哈希表的話,我們只需要申請(qǐng)一個(gè)長(zhǎng)度為3的數(shù)組(與待查找的元素個(gè)數(shù)相同),如下圖所示:
將1/5/8分別對(duì)數(shù)組長(zhǎng)度3做取模運(yùn)算,然后把它們指向運(yùn)算結(jié)果對(duì)應(yīng)的數(shù)組槽位,這樣就把一組離散的數(shù)據(jù)映射到了連續(xù)的空間中,從而在最大限度上提高了空間的利用率,并且也提高了元素的查找效率。
但可能會(huì)出現(xiàn)一個(gè)問題,數(shù)字5、8映射到同一個(gè)槽位上,這樣就導(dǎo)致其中一個(gè)數(shù)字無法查找到。上述這種情況在實(shí)際中也會(huì)遇到,我們把它稱為“哈希沖突”或者“哈希碰撞”。
解決哈希沖突:
有許多方法可以解決“哈希沖突”,比如開放地址法、鏈表地址法,再次散列法等,而Redis采用是鏈表地址法。
將有沖突的數(shù)據(jù)使用鏈表把它們串聯(lián)起來,這樣即使發(fā)生了沖突,也可以將數(shù)據(jù)存儲(chǔ)在一起,最后,通過遍歷鏈表的方式就找到上述發(fā)生“沖突”的數(shù)據(jù)。
如下所示:
如果值是字符串的話,就需要通過哈希函數(shù)將字符串轉(zhuǎn)換成具體的數(shù)值,然后再對(duì)其進(jìn)行映射。
設(shè)置與獲取(hset和hget)
哈希類型可以通過hset命令來設(shè)置數(shù)據(jù),通過hget命令來讀取數(shù)據(jù)。
hset的命令格式如下
hset key field value [field value ...]
其中key是待緩存對(duì)象的鍵,field value是以鍵值對(duì)的形式描述的對(duì)象數(shù)據(jù)。
針對(duì)同一個(gè)key,可以用多個(gè)field value對(duì)來存儲(chǔ)數(shù)據(jù),這里field可以理解成對(duì)象的屬性名,value可以理解成對(duì)象的屬性值。
hget的命令格式如下,其中key是待讀取對(duì)象的鍵,如果存在key和field所對(duì)應(yīng)的數(shù)據(jù),則返回該數(shù)據(jù),否則返回null值。僅傳入key而不傳入field參數(shù),會(huì)報(bào)錯(cuò)。
hget key field
示例:
hsetnx命令
用hset命令設(shè)置哈希類型的變量時(shí),如果出現(xiàn)重復(fù),就會(huì)用后設(shè)的數(shù)據(jù)覆蓋掉之前的數(shù)據(jù)。
與之對(duì)應(yīng)的是hsetnx命令
hsetnx key field value
只有當(dāng)key和field所對(duì)應(yīng)的value不存在時(shí)才會(huì)設(shè)置對(duì)應(yīng)的value,而且key之后只能帶一對(duì)field和value
hset命令的key之后能帶多個(gè)field和value對(duì)。
針對(duì)key的相關(guān)操作
通過hkeys key命令,能查看該key所對(duì)應(yīng)哈希類型數(shù)據(jù)的所有field;
通過hvals key命令,能查看key所對(duì)應(yīng)哈希類型數(shù)據(jù)的所有value;
通過hgetall key命令,能以field和value對(duì)的形式查看key對(duì)應(yīng)的哈希類型數(shù)據(jù)。
hexists命令
通過hexists命令,能判斷key和field對(duì)應(yīng)的value是否存在。
hexists命令的格式:
hexists key field
對(duì)哈希類型數(shù)據(jù)的刪除操作:
通過hdel命令,能刪除key指定的field數(shù)據(jù),該命令的格式如下:
hdel key field [field...]
通過該命令能同時(shí)刪除一個(gè)key對(duì)應(yīng)的多個(gè)field數(shù)據(jù)。如果要?jiǎng)h除指定key所對(duì)應(yīng)的整個(gè)哈希類型的數(shù)據(jù),則需要用del key命令。
基本數(shù)據(jù)類型List
Redis list(列表)相當(dāng)于Java語言中的LinkedList結(jié)構(gòu),是一個(gè)鏈表而非數(shù)組,其插入、刪除元素的時(shí)間復(fù)雜度為O(1),但是查詢速度欠佳,時(shí)間復(fù)雜度為O(n)。
當(dāng)向列表中添加元素值時(shí),首先需要給這個(gè)列表指定一個(gè)key鍵,然后使用相應(yīng)的命令,從列表的左側(cè)(頭部)或者右側(cè)(尾部)來添加元素,這些元素會(huì)以添加時(shí)的順序排列。
當(dāng)列表彈出(pop)最后一個(gè)元素時(shí),該結(jié)構(gòu)會(huì)被自動(dòng)刪除。
Redis列表的底層存儲(chǔ)結(jié)構(gòu),其實(shí)是一個(gè)被稱為快速鏈表(quicklist)的結(jié)構(gòu)。
當(dāng)列表中存儲(chǔ)的元素較少時(shí):
Redis 使用一塊連續(xù)的內(nèi)存來存儲(chǔ)這些元素這個(gè)連續(xù)的結(jié)構(gòu)被稱為ziplist(壓縮列表),它將所有的元素緊挨著一起存儲(chǔ)。使用壓縮列表來做列表的底層實(shí)現(xiàn)的情況:
? ? ? ?(1) 當(dāng)一個(gè)列表只包含少量列表項(xiàng),并且每個(gè)列表項(xiàng)要么就是小整數(shù)值要么就是長(zhǎng)度比較短的字符串,
? ? ? ? (2)當(dāng)一個(gè)哈希只包含少量鍵值對(duì),比且每個(gè)鍵值對(duì)的鍵和值要么就是小整數(shù)值,要么就是長(zhǎng)度比較短的字符串,
壓縮列表是Redis為了節(jié)約內(nèi)存而開發(fā)的,是由一系列特殊編碼的連續(xù)內(nèi)存塊組成的順序型(sequential))數(shù)據(jù)結(jié)構(gòu)。
一個(gè)壓縮列表可以包含任意多個(gè)節(jié)點(diǎn)(entry),每個(gè)節(jié)點(diǎn)可以保存一個(gè)字節(jié)數(shù)組或者一個(gè)整數(shù)值。
當(dāng)列表中存儲(chǔ)的元素較多時(shí):
Redis列表用quicklist(快速鏈表)存儲(chǔ)元素。
Redis之所以采用兩種方法相結(jié)合的方式來存儲(chǔ)元素,這是因?yàn)閱为?dú)使用普通鏈表存儲(chǔ)元素時(shí),所需的空間較大,會(huì)造成存儲(chǔ)空間的浪費(fèi)。因此采用了鏈表和壓縮列表相結(jié)合的方式,也就是quicklist+ziplist,結(jié)構(gòu)如下圖:
將多個(gè)ziplist使用雙向指針串聯(lián)起來,這樣既能滿足快速插入、刪除的特性,又節(jié)省了一部分存儲(chǔ)空間。
設(shè)置與獲取:
可以通過lpush命令把一個(gè)或多個(gè)值依次且一次性插入到列表的頭部,因此讀取索引號(hào)是0的數(shù)據(jù)時(shí),返回的是最后插入的數(shù)據(jù)。
key指定待插入的列表,element表示插入到列表的值。
lpush key element [element ...]
也可以用rpush命令在指定列表的尾部插入數(shù)據(jù),該命令格式如下:
rpush key element [element ...]
可以通過lindex命令讀取列表的值,key指定待讀取的列表,index指定待讀取列表值的索引號(hào)。注意,索引號(hào)是從0開始的。
lindex key index
示例:
模擬堆棧和隊(duì)列:
lpush:向左邊(list頭)添加數(shù)據(jù)。rpush:向右邊(list尾)添加數(shù)據(jù)
與之對(duì)應(yīng)的有lpop和rpop命令,表示分別從Iist頭和list尾讀數(shù)據(jù),而且讀完會(huì)把該數(shù)據(jù)從列表里彈出(移除)。
通過如下的lpush和lpop命令能模擬"先入后出”的堆棧效果:
還可以通過lpush和rpop命令來模擬“先來先服務(wù)”的隊(duì)列效果:
lrange:
通過lrange命令可以獲取指定區(qū)間內(nèi)的數(shù)據(jù),start和stop分別表示開始索引和結(jié)束索引。
該命令的格式:
lrange key start stop
start <= stop時(shí),才會(huì)取出數(shù)據(jù)。負(fù)數(shù)則表示倒數(shù)第幾個(gè)。
獲取列表包含的所有元素:
快捷方法:使用0作為起始索引、-1作為結(jié)束索引去調(diào)用lrange命令,這種方法非常適合于查看長(zhǎng)度較短的列表。
列表中的最后一個(gè)元素索引為-1,依次類推。
修改列表中的元素:
通過lset命令能修改列表里的元素,能把由key指定的列表里index的數(shù)據(jù)修改為element。
該命令的格式:
lset key index element
將元素插入列表
通過使用linsert命令,用戶可以將一個(gè)新元素插入列表某個(gè)指定元素的前面或者后面:
linsert list BEFORE|AFTER target_element new_element
linsert命令第二個(gè)參數(shù)的值可以是before或after,它們分別用于指示命令將新元素插入目標(biāo)元素的前面或后面
獲取列表的長(zhǎng)度:
用戶可以通過執(zhí)行llen命令來獲取列表的長(zhǎng)度,即列表包含的元素?cái)?shù)量:
llen list
移除指定的元素:
可以通過lrem命令刪除列表里的指定元素,該命令的格式如下:
lrem key count element
當(dāng)count = 0時(shí),刪除該列表里所有值是element的數(shù)據(jù);
當(dāng)count > 0時(shí),刪除從頭到尾方向數(shù)量為count個(gè)、值是element的數(shù)據(jù);(從左往右刪除)
當(dāng)count < 0時(shí),刪除從尾到頭方向數(shù)量為count個(gè)、值是element的數(shù)據(jù)。(從右往左刪除)
修剪列表:
ltrim命令接受一個(gè)列表和一個(gè)索引范圍作為參數(shù),并移出列表中位于給定索引范圍之外的所有元素,只保留給定范圍之內(nèi)的元素:
LTRIM list start end
LTRM命令在執(zhí)行完移除操作之后將返回OK作為結(jié)果。
基本數(shù)據(jù)類型Set
Set類型:
Redis的集合(set)鍵允許用戶將任意多個(gè)各不相同的元素存儲(chǔ)到集合中,這些元素既可以是文本數(shù)據(jù),也可以是二進(jìn)制數(shù)據(jù)。
雖然都可以存儲(chǔ)多個(gè)元素,但集合與列表有以下兩個(gè)明顯的區(qū)別:
(1)列表可以存儲(chǔ)重復(fù)元素,而集合只會(huì)存儲(chǔ)非重復(fù)元素,嘗試將一個(gè)已存在的元素添加到集合將被忽略。
(2)列表以有序方式存儲(chǔ)元素,而集合則以無序方式存儲(chǔ)元素。
這兩個(gè)區(qū)別帶來的差異主要跟命令的復(fù)雜度有關(guān):
在執(zhí)行像LINSERT和LREM這樣的列表命令時(shí),即使命令只針對(duì)單個(gè)列表元素,程序有時(shí)也不得不遍歷整個(gè)列表以確定指定的元素是否存在,因此這些命令的復(fù)雜度都為O(N)。
對(duì)于集合來說,因?yàn)樗嗅槍?duì)單個(gè)元素的集合命令都不需要遍歷整個(gè)集合,所以復(fù)雜度都為O(1)。
因此當(dāng)我們需要存儲(chǔ)多個(gè)元素時(shí),就可以考慮這些元素是否可以以無序的方式存儲(chǔ),并且是否不會(huì)出現(xiàn)重復(fù)。如果是,那么就可以使用集合來存儲(chǔ)這些元素,從而有效地利用集合操作的效率優(yōu)勢(shì)。
將新元素添加到集合中:
使用sadd命令將一個(gè)或多個(gè)元素添加到集合中,命令格式如下:
sadd set element [element ...]
用sadd添加元素時(shí),會(huì)自動(dòng)忽略已存在的元素,只將不存在于集合的新元素添加到集合中。
集合中移除已有的元素
使用srem命令將一個(gè)或多個(gè)元素從集合中移除
srem set element [element ...]
這個(gè)命令會(huì)返回被移除的元素?cái)?shù)量:
將指定的元素從一個(gè)集合移動(dòng)到另一個(gè)集合
smove命令允許用戶將指定的元素從源集合移動(dòng)到目標(biāo)集合:
smove source target element
smove命令在移動(dòng)操作成功執(zhí)行時(shí)返回1。如果指定的元素并不存在于源集合,那么smove命令將返回0,表示移動(dòng)操作執(zhí)行失敗。
獲取集合包含的所有元素
通過使用smembers命令,用戶可以取得集合包含的所有元素:
smembers set
因?yàn)镽edis集合以無序的方式存儲(chǔ)元素,并且SMEMBERS命令在獲取集合元素時(shí)也不會(huì)對(duì)元素進(jìn)行任何排序動(dòng)作,所以根據(jù)元素添加順序的不同,2個(gè)包含相同元素的集合在執(zhí)行SMEMBERS命令時(shí)的結(jié)果也可能會(huì)有所不同。
獲取集合包含的元素?cái)?shù)量
通過scard命令,用戶可以獲取給定集合的大小,即集合包含的元素?cái)?shù)量:
scard set
檢查給定元素是否存在于集合中
使用sismember命令:
sismember set element
從集合中隨機(jī)地獲取指定數(shù)量的元素:
通過使用SRANDMEMBER命令,用戶可以從集合中隨機(jī)地獲取指定數(shù)量的元素。
SRANDMEMBER命令接受一個(gè)可選的count參數(shù),用于指定用戶想要獲取的元素?cái)?shù)量,如果用戶沒有給定這個(gè)參數(shù),那么SRANDMEMBER命令默認(rèn)只獲取一個(gè)元素:
SRANDMEMBER set [count]
被SRANDMEMBER命令返回的元素仍然會(huì)存在于集合當(dāng)中。
若count參數(shù)的值為正數(shù),SRANDMEMBER命令將返回count個(gè)不重復(fù)的元素。
若count參數(shù)的值為負(fù)數(shù),SRANDMEMBER命令將隨機(jī)返回abs(count)個(gè)元素,并且在這些元素當(dāng)中允許出現(xiàn)重復(fù)的元素。
隨機(jī)從集合中移除指定數(shù)量的元素:
SPOP命令接受一個(gè)可選的cout參數(shù),用于指定需要被移除的元素?cái)?shù)量。如果用戶沒有給定這個(gè)參數(shù),那么SPOP命令默認(rèn)只移除一個(gè)元素:
spop key [count]
SPOP命令只接受正數(shù)count值,如果向SPOP命令提供負(fù)數(shù)count值將引發(fā)錯(cuò)誤,因?yàn)樨?fù)數(shù)count值對(duì)于SPOP命令是沒有意義的
集合運(yùn)算:
sinter命令可以計(jì)算用戶給定的所有集合的交集,然后返回這個(gè)交集包含的所有元素:
sinter set [set..,]
sunion命令可以計(jì)算出用戶給定的所有集合的并集,然后返回這個(gè)并集包含的所有元素:
sunion set [set..,]
sdiff命令可以計(jì)算出給定集合之間的差集,并返回差集包含的所有元素:
sdiff set [set..,]
有序集合:
Redis的有序集合(sorted set)同時(shí)具有“有序”和“集合”兩種性質(zhì)。
這種數(shù)據(jù)結(jié)構(gòu)中的每個(gè)元素都由一個(gè)成員和一個(gè)與成員相關(guān)聯(lián)的分值組成,其中成員以字符串方式存儲(chǔ),而分值則以64位雙精度浮點(diǎn)數(shù)格式存儲(chǔ)。
與集合一樣,有序集合中的每個(gè)成員都是獨(dú)一無二的,同一個(gè)有序集合中不會(huì)出現(xiàn)重復(fù)的成員。有序集合的成員將按照它們各自的分值大小進(jìn)行排序:比如,分值為3.14的成員將小于分值為10.24的成員,而分值為999的成員也會(huì)小于分值為10086的成員。
有序集合的分值除了可以是數(shù)字之外,還可以是字符串" +inf? "或者" -inf ",這兩個(gè)特殊值分別用于表示無窮大和無窮小。
同一個(gè)有序集合不能存儲(chǔ)相同的成員,但不同成員的分值卻可以是相同的。
當(dāng)兩個(gè)或多個(gè)成員擁有相同的分值時(shí),Rdis將按照這些成員在字典序中的大小對(duì)其進(jìn)行排列:
舉個(gè)例子,如果成員"apple"和成員"zero"都擁有相同的分值100,那么Redis將認(rèn)為成員"apple"小于成員"zero",這是因?yàn)樵?strong>字典序中,字母"a"開頭的單詞要小于字母"z"開頭的單詞。
有序集合是Redis提供的所有數(shù)據(jù)結(jié)構(gòu)中最為靈活的一種,它可以以多種不同的方式獲取數(shù)據(jù),比如根據(jù)成員獲取分值、根據(jù)分值獲取成員、根據(jù)成員的排名獲取成員、根據(jù)指定的分值范圍獲取多個(gè)成員等。
有序集合_添加或更新成員:
使用ZADD命令,用戶可以向有序集合添加一個(gè)或多個(gè)新成員:
zadd sorted_set score member [score member ...]
ZADD命令除了可以向有序集合添加新成員之外,還可以對(duì)有序集合中已存在成員的分值進(jìn)行更新:
????????在默認(rèn)情況下,如果用戶在執(zhí)行ZADD命令時(shí),給定成員已經(jīng)存在于有序集合中,并且給定的分值和成員現(xiàn)有的分值并不相同,那么ZADD命令將使用給定的新分值去覆蓋現(xiàn)有的舊分值。
有序集合_移除指定的成員:
通過使用ZREM命令,用戶可以從有序集合中移除指定的一個(gè)或多個(gè)成員以及與這些成員相關(guān)聯(lián)的分值:
zrem sorted_set member [member...]
通過使用ZSCORE命令,用戶可以獲取與給定成員相關(guān)聯(lián)的分值:
zscore sorted_set member
有序集合_對(duì)成員分值執(zhí)行自增或自減操作:
使用ZINCRBY命令,對(duì)有序集合中指定成員的分值執(zhí)行自增操作,為其加上指定的增量。
zincrby sorted_set increment member
redis沒有相應(yīng)的自減操作,所以可以將一個(gè)負(fù)數(shù)增量傳給ZINCRBY命令,達(dá)到對(duì)分值的自減操作。
有序集合_獲取成員在有序集合中的排名:
排名標(biāo)記是從0開始的。
ZRANK命令返回的是成員的升序排列排名,即成員在按照分值從小到大進(jìn)行排列時(shí)的排名
ZRANK sorted_set member
ZREVRANK命令返回的則是成員的降序排列排名,即成員在按照分值從大到小進(jìn)行排列時(shí)的排名。
ZREVRANK sorted_set member
有序集合_獲取指定索引范圍內(nèi)的成員:
排名標(biāo)記是從0開始的。
ZRANGE命令返回的是在索引范圍內(nèi)成員的升序排列排名,即成員在按照分值從小到大進(jìn)行排列時(shí)的排名
zrange sorted_set start end
ZREVRANGE命令返回的則是在索引范圍內(nèi)成員的降序排列排名,即成員在按照分值從大到小進(jìn)行排列時(shí)的排名。
zrevrange sorted_set start end
有序集合_獲取指定分值范圍內(nèi)的成員:
ZRANGEBYSCORE以升序排列的方式獲取有序集合中分值介于指定范圍內(nèi)的成員:
ZRANGEBYSCORE sorted_set min max
ZREVRANGEBYSCORE以降序排列的方式獲取有序集合中分值介于指定范圍內(nèi)的成員:
ZREVRANGEBYSCORE sorted_set max min
命令的min參數(shù)和max參數(shù)分別用于指定用戶想要獲取的成員的最小分值和最大分值
ZRANGEBYSCORE命令和ZREVRANGEBYSCORE命令接受min參數(shù)和max參數(shù)的順序正好相反。
有序集合_統(tǒng)計(jì)指定分值范圍內(nèi)的成員數(shù)量
使用ZCOUNT命令,可以統(tǒng)計(jì)出有序集合中分值介于指定范圍之內(nèi)的成員數(shù)量:
zcount sorted_set min max
范圍控制:
ZRANGEBYSCORE、ZCOUNT等命令可以控制區(qū)間的開合。上述命令接受的分值范圍都是閉區(qū)間分值范圍。
如果用戶想要定義的是開區(qū)間而不是閉區(qū)間,那么可以在給定分值范圍時(shí),在分值參數(shù)的前面加上一個(gè)單括號(hào)“(”,這樣,具有給定分值的成員就不會(huì)出現(xiàn)在命令返回的結(jié)果當(dāng)中。
min參數(shù)和max參數(shù)除了可以是普通的分值或者帶有(符號(hào)的分值之外,還可以是特殊值+inf或者-inf。前者用于表示無窮大,而后者則用于表示無窮小。