天天看點

Redis---set資料類型操作

在redis中,我們可以将set類型看作為沒有排序的字元集合,和list類型一樣,我們也可以在該類型的資料值上執行添加、删除或判斷某一進制素是否存在等操作。需要說明的是,這些操作的時間複雜度為o(1),即常量時間内完成次操作。set可包含的最大元素數量是4294967295。

和list類型不同的是,set集合中不允許出現重複的元素,這一點和c++标準庫中的set容器是完全相同的。換句話說,如果多次添加相同元素,set中将僅保留該元素的一份拷貝。和list類型相比,set類型在功能上還存在着一個非常重要的特性,即在伺服器端完成多個sets之間的聚合計算操作,如unions、intersections和differences。由于這些操作均在服務端完成,是以效率極高,而且也節省了大量的網絡io開銷。

指令原型

時間複雜度

指令描述

傳回值

sadd key member [member …]

o(n)

時間複雜度中的n表示操作的成員數量。如果在插入的過程用,參數中有的成員在set中已經存在,該成員将被忽略,而其它成員仍将會被正常插入。如果執行該指令之前,該key并不存在,該指令将會建立一個新的set,此後再将參數中的成員陸續插入。

如果該key的value不是set類型,該指令将傳回相關的錯誤資訊。 本次操作實際插入的成員數量。

scard key

o(1)

擷取set中成員的數量。

傳回set中成員的數量,如果該key并不存在,傳回0。

sismember key member

判斷參數中指定成員是否已經存在于與key相關聯的set集合中。

1表示已經存在,0表示不存在,或該key本身并不存在。

smembers key

時間複雜度中的n表示set中已經存在的成員數量。擷取與該key關聯的set中所有的成員。

傳回set中所有的成員。

spop key

随機的移除并傳回set中的某一成員。 由于set中元素的布局不受外部控制,是以無法像list那樣确定哪個元素位于set的頭部或者尾部。

傳回移除的成員,如果該key并不存在,則傳回nil。

srem key member [member …]

時間複雜度中的n表示被删除的成員數量。從與key關聯的set中删除參數中指定的成員,不存在的參數成員将被忽略,如果該key并不存在,将視為空set處理。

從set中實際移除的成員數量,如果沒有則傳回0。

srandmember key

和spop一樣,随機的傳回set中的一個成員,不同的是該指令并不會删除傳回的成員。

傳回随機位置的成員,如果key不存在則傳回nil。

smove source destination member

原子性的将參數中的成員從source鍵移入到destination鍵所關聯的set中。是以在某一時刻,該成員或者出現在source中,或者出現在destination中。如果該成員在source中并不存在,該指令将不會再執行任何操作并傳回0,否則,該成員将從source移入到destination。如果此時該成員已經在destination中存在,那麼該指令僅是将該成員從source中移出。如果和key關聯的value不是set,将傳回相關的錯誤資訊。

1表示正常移動,0表示source中并不包含參數成員。

sdiff key [key …]

時間複雜度中的n表示所有sets中成員的總數量。傳回參數中第一個key所關聯的set和其後所有keys所關聯的sets中成員的差異。如果key不存在,則視為空set。

差異結果成員的集合。

sdiffstore destination key [key …]

該指令和sdiff指令在功能上完全相同,兩者之間唯一的差别是sdiff傳回差異的結果成員,而該指令将差異成員存儲在destination關聯的set中。如果destination鍵已經存在,該操作将覆寫它的成員。

傳回差異成員的數量。

sinter key [key …]

o(n*m)

時間複雜度中的n表示最小set中元素的數量,m則表示參數中sets的數量。該指令将傳回參數中所有keys關聯的sets中成員的交集。是以如果參數中任何一個key關聯的set為空,或某一key不存在,那麼該指令的結果将為空集。

交集結果成員的集合。

sinterstore destination key [key …]

該指令和sinter指令在功能上完全相同,兩者之間唯一的差别是sinter傳回交集的結果成員,而該指令将交內建員存儲在destination關聯的set中。如果destination鍵已經存在,該操作将覆寫它的成員。

傳回交內建員的數量。

sunion key [key …]

時間複雜度中的n表示所有sets中成員的總數量。該指令将傳回參數中所有keys關聯的sets中成員的并集。

并集結果成員的集合。

sunionstore destination key [key …]

該指令和sunion指令在功能上完全相同,兩者之間唯一的差别是sunion傳回并集的結果成員,而該指令将并內建員存儲在destination關聯的set中。如果destination鍵已經存在,該操作将覆寫它的成員。

傳回并內建員的數量。

sadd/smembers/scard/sismember:

在shell指令行下啟動redis的用戶端程式。

/> redis-cli

插入測試資料,由于該鍵myset之前并不存在,是以參數中的三個成員都被正常插入。

redis 127.0.0.1:6379> sadd myset a b c

(integer) 3

由于參數中的a在myset中已經存在,是以本次操作僅僅插入了d和e兩個新成員。

redis 127.0.0.1:6379> sadd myset a d e

(integer) 2

判斷a是否已經存在,傳回值為1表示存在。

redis 127.0.0.1:6379> sismember myset a

(integer) 1

判斷f是否已經存在,傳回值為0表示不存在。

redis 127.0.0.1:6379> sismember myset f

(integer) 0

通過smembers指令檢視插入的結果,從結果可以,輸出的順序和插入順序無關。

redis 127.0.0.1:6379> smembers myset

1) “c”

2) “d”

3) “a”

4) “b”

5) “e”

擷取set集合中元素的數量。

redis 127.0.0.1:6379> scard myset

(integer) 5

spop/srem/srandmember/smove:

删除該鍵,便于後面的測試。

redis 127.0.0.1:6379> del myset

為後面的示例準備測試資料。

redis 127.0.0.1:6379> sadd myset a b c d

(integer) 4

檢視set中成員的位置。

從結果可以看出,該指令确實是随機的傳回了某一成員。

redis 127.0.0.1:6379> srandmember myset

“c”

set中尾部的成員b被移出并傳回,事實上b并不是之前插入的第一個或最後一個成員。

redis 127.0.0.1:6379> spop myset

“b”

檢視移出後set的成員資訊。

從set中移出a、d和f三個成員,其中f并不存在,是以隻有a和d兩個成員被移出,傳回為2。

redis 127.0.0.1:6379> srem myset a d f

檢視移出後的輸出結果。

為後面的smove指令準備資料。

redis 127.0.0.1:6379> sadd myset a b

redis 127.0.0.1:6379> sadd myset2 c d

将a從myset移到myset2,從結果可以看出移動成功。

redis 127.0.0.1:6379> smove myset myset2 a

再次将a從myset移到myset2,由于此時a已經不是myset的成員了,是以移動失敗并傳回0。

分别檢視myset和myset2的成員,确認移動是否真的成功。

1) “b”

redis 127.0.0.1:6379> smembers myset2

sdiff/sdiffstore/sinter/sinterstore:

為後面的指令準備測試資料。

redis 127.0.0.1:6379> sadd myset2 c

redis 127.0.0.1:6379> sadd myset3 a c e

myset和myset2相比,a、b和d三個成員是兩者之間的差異成員。再用這個結果繼續和myset3進行差異比較,b和d是myset3不存在的成員。

redis 127.0.0.1:6379> sdiff myset myset2 myset3

1) “d”

2) “b”

将3個集合的差異成員存在在diffkey關聯的set中,并傳回插入的成員數量。

redis 127.0.0.1:6379> sdiffstore diffkey myset myset2 myset3

檢視一下sdiffstore的操作結果。

redis 127.0.0.1:6379> smembers diffkey

從之前準備的資料就可以看出,這三個set的成員交集隻有c。

redis 127.0.0.1:6379> sinter myset myset2 myset3

将3個集合中的交內建員存儲到與interkey關聯的set中,并傳回交內建員的數量。

redis 127.0.0.1:6379> sinterstore interkey myset myset2 myset3

檢視一下sinterstore的操作結果。

redis 127.0.0.1:6379> smembers interkey

擷取3個集合中的成員的并集。

redis 127.0.0.1:6379> sunion myset myset2 myset3

2) “c”

3) “d”

4) “e”

5) “a”

将3個集合中成員的并集存儲到unionkey關聯的set中,并傳回并內建員的數量。

redis 127.0.0.1:6379> sunionstore unionkey myset myset2 myset3

檢視一下suiionstore的操作結果。

redis 127.0.0.1:6379> smembers unionkey

1). 可以使用redis的set資料類型跟蹤一些唯一性資料,比如通路某一部落格的唯一ip位址資訊。對于此場景,我們僅需在每次通路該部落格時将通路者的ip存入redis中,set資料類型會自動保證ip位址的唯一性。

2). 充分利用set類型的服務端聚合操作友善、高效的特性,可以用于維護資料對象之間的關聯關系。比如所有購買某一電子裝置的客戶id被存儲在一個指定的set中,而購買另外一種電子産品的客戶id被存儲在另外一個set中,如果此時我們想擷取有哪些客戶同時購買了這兩種商品時,set的intersections指令就可以充分發揮它的友善和效率的優勢了。

3).很容易實作資料庫中的關聯表查詢。