1. 程式人生 > >Redis資料型別以及操作

Redis資料型別以及操作

第二章 Redis 資料型別及操作

 2.1 前言

Redis 的作者 antirez(Salvatore Sanfilippo)曾經發表了一篇名為 Redis 宣言(Redis Manifesto) 的文章,文中列舉了 Redis 的七個原則,以向大家闡明 Redis 的思想。

1、Redis 是一個操作資料結構的語言工具,它提供基於 TCP  的協議以操作豐富的資料結構。在 Redis 中,資料結構這個詞的意義不僅表示在某種資料結構上的操作,更包括了結構本身及這些操作的時間空間複雜度。

2、Redis 定位於一個記憶體資料庫,正是由於記憶體的快速訪問特性,才使得 Redis  能夠有如此高的效能,才使得 Redis 能夠輕鬆處理大量複雜的資料結構,Redis 會嘗試其它的儲存方面的選擇,但是永遠不會改變它是一個記憶體資料庫的角色。

3、Redis 使用基礎的 API 操作基礎的資料結構,Redis 的 API 與資料結構一樣,都是一些最基礎的元素,你幾乎可以將任何資訊互動使用此 API 格式表示。作者調侃說,如果有其它非人類的智慧生物存在,他們也能理解 Redis 的 API。因為它是如此的基礎。

4、Redis 有著詩一般優美的程式碼,經常有一些不太瞭解 Redis 有的人會建議 Redis 採用一些其它人的程式碼,以實現一些 Redis 未實現的功能,但這對我們來說就像是非要給《紅樓夢》接上後四十回一樣。

5、Redis 始終避免複雜化,我們認為設計一個系統的本質,就是與複雜化作戰。我們不會為了一個小功能而往原始碼裡新增上千行程式碼,解決複雜問題的方法就是讓複雜問題永遠不要提複雜的問題。

6、Redis 支援兩個層成的 API,第一個層面包含部分操作 API,但它支援用於分散式環境下的 Redis。第二個層面的 API 支援更復雜的 multi-key 操作。它們各有所長,但是我們不會推出兩者都支援的 API,但我們希望能夠提供例項間資料遷移的命令,並執行 multi-key 操作。

7、我們以優化程式碼為樂,我們相信編碼是一件辛苦的工作,唯一對得起這辛苦的就是去享受它。如果我們在編碼中失去了樂趣,那最好的解決辦法就是停下來。我們決不會選擇讓Redis 不好玩的開發模式。

Redis 的作者 antirez 曾笑稱 Redis 為一個數據結構伺服器(data structures server),我認為這是一個非常準確的表述,Redis 的所有功能就是將資料以其固有的幾種結構來儲存,並提供給使用者操作這幾種結構的介面。本文將介紹 Redis 支援的各種資料型別及其操作介面。

2.2 strings 型別及操作

string 是最簡單的型別,你可以理解成與 Memcached 是一模一樣的型別,一個 key 對應一個

value,其上支援的操作與 Memcached 的操作類似。但它的功能更豐富。

string 型別是二進位制安全的。意思是 redis 的 string 可以包含任何資料,比如 jpg 圖片或者序列化的物件。從內部實現來看其實 string 可以看作 byte 陣列,最大上限是 1G 位元組,下面是

string 型別的定義:

struct sdshdr

{ long len;

long free;

char buf[];

};

len 是 buf 陣列的長度。

free 是陣列中剩餘可用位元組數,由此可以理解為什麼 string 型別是二進位制安全的了,因為它本質上就是個 byte 陣列,當然可以包含任何資料了

buf 是個 char 陣列用於存貯實際的字串內容,其實 char 和 c#中的 byte 是等價的,都是一個位元組。

另外 string 型別可以被部分命令按 int 處理.比如 incr 等命令,如果只用 string 型別,redis 就可以被看作加上持久化特性的 memcached。當然 redis 對 string 型別的操作比 memcached 還是多很多的,具體操作方法如下:

2.2.1 set

設定 key 對應的值為 string 型別的 value。

例如我們新增一個 name= HongWan 的鍵值對,可以這樣做:

redis 127.0.0.1:6379> set name HongWan

OK

redis 127.0.0.1:6379>

2.2.2 setnx

設定 key 對應的值為 string 型別的 value。如果 key 已經存在,返回 0,nx 是 not exist 的意思。例如我們新增一個 name= HongWan_new 的鍵值對,可以這樣做:

redis 127.0.0.1:6379> setnx name HongWan_new

(integer) 0

redis 127.0.0.1:6379> get name "HongWan"

redis 127.0.0.1:6379>

2.2.3 setex

設定 key 對應的值為 string 型別的 value,並指定此鍵值對應的有效期。

例如我們新增一個 haircolor= red 的鍵值對,並指定它的有效期是 10 秒,可以這樣做:

redis 127.0.0.1:6379> setex haircolor 10 red

OK

redis 127.0.0.1:6379> get haircolor "red"

redis 127.0.0.1:6379> get haircolor

(nil)

redis 127.0.0.1:6379>

2.2.4 setrange

設定指定 key 的 value 值的子字串。

例如我們希望將 HongWan 的 126 郵箱替換為 gmail 郵箱,那麼我們可以這樣做:

redis 127.0.0.1:6379> get name "[email protected]"

redis 127.0.0.1:6379> setrange name 8 gmail.com

(integer) 17

redis 127.0.0.1:6379> get name "[email protected]gmail.com"

redis 127.0.0.1:6379>

其中的 8 是指從下標為 8(包含 8)的字元開始替換

2.2.5 mset

一次設定多個 key 的值,成功返回 ok 表示所有的值都設定了,失敗返回 0 表示沒有任何值被設定。

redis 127.0.0.1:6379> mset key1 HongWan1 key2 HongWan2

OK

redis 127.0.0.1:6379> get key1 "HongWan1"

redis 127.0.0.1:6379> get key2

"HongWan2"

redis 127.0.0.1:6379>

2.2.6 msetnx

一次設定多個 key 的值,成功返回 ok 表示所有的值都設定了,失敗返回 0 表示沒有任何值被設定,但是不會覆蓋已經存在的 key。

redis 127.0.0.1:6379> get key1 "HongWan1"

redis 127.0.0.1:6379> get key2 "HongWan2"

redis 127.0.0.1:6379> msetnx key2 HongWan2_new key3 HongWan3 (integer) 0

redis 127.0.0.1:6379> get key2 "HongWan2"

redis 127.0.0.1:6379> get key3

(nil)

可以看出如果這條命令返回 0,那麼裡面操作都會回滾,都不會被執行。

2.2.7 get

獲取 key 對應的 string 值,如果 key 不存在返回 nil。

例如我們獲取一個庫中存在的鍵 name,可以很快得到它對應的 value

redis 127.0.0.1:6379> get name

"HongWan"

redis 127.0.0.1:6379>

2.2.8 getset

設定 key 的值,並返回 key 的舊值。

redis 127.0.0.1:6379> get name "HongWan"

redis 127.0.0.1:6379> getset name HongWan_new

"HongWan"

redis 127.0.0.1:6379> get name "HongWan_new"

redis 127.0.0.1:6379>

接下來我們看一下如果 key 不存的時候會什麼樣兒?

redis 127.0.0.1:6379> getset name1 aaa

(nil)

redis 127.0.0.1:6379>

可見,如果 key 不存在,那麼將返回 nil

2.2.9 getrange

獲取指定 key 的 value 值的子字串。具體樣例如下:

redis 127.0.0.1:6379> get name "[email protected]"

redis 127.0.0.1:6379> getrange name 0 6

"HongWan"

redis 127.0.0.1:6379>

字串左面下標是從 0 開始的

redis 127.0.0.1:6379> getrange name -7 -1

"126.com"

redis 127.0.0.1:6379>

字串右面下標是從-1 開始的

redis 127.0.0.1:6379> getrange name 7 100

"@126.com"

redis 127.0.0.1:6379>

當下標超出字串長度時,將預設為是同方向的最大下標

2.2.10 mget

一次獲取多個 key 的值,如果對應 key 不存在,則對應返回 nil。具體樣例如下:

redis 127.0.0.1:6379> mget key1 key2 key3

  1. "HongWan1"
  2. "HongWan2"
  3. (nil)

redis 127.0.0.1:6379>

key3 由於沒有這個鍵定義,所以返回 nil。

2.2.11 incr

對 key 的值做加加操作,並返回新的值。注意 incr 一個不是 int 的 value 會返回錯誤,incr 一個不存在的 key,則設定 key 為 1

redis 127.0.0.1:6379> set age 20 OK

redis 127.0.0.1:6379> incr age

(integer) 21

redis 127.0.0.1:6379> get age "21"

redis 127.0.0.1:6379>

2.2.12 incrby

同 incr 類似,加指定值 ,key 不存在時候會設定 key,並認為原來的 value 是 0

redis 127.0.0.1:6379> get age "21"

redis 127.0.0.1:6379> incrby age 5

(integer) 26

redis 127.0.0.1:6379> get name "[email protected]"

redis 127.0.0.1:6379> get age "26"

redis 127.0.0.1:6379>

2.2.13 decr

對 key 的值做的是減減操作,decr 一個不存在 key,則設定 key 為-1

redis 127.0.0.1:6379> get age "26"

redis 127.0.0.1:6379> decr age

(integer) 25

redis 127.0.0.1:6379> get age "25"

redis 127.0.0.1:6379>

2.2.14 decrby

同 decr,減指定值。

redis 127.0.0.1:6379> get age "25"

redis 127.0.0.1:6379> decrby age 5

(integer) 20

redis 127.0.0.1:6379> get age "20"

redis 127.0.0.1:6379>

decrby 完全是為了可讀性,我們完全可以通過 incrby 一個負值來實現同樣效果,反之一樣

redis 127.0.0.1:6379> get age "20"

redis 127.0.0.1:6379> incrby age -5

(integer) 15

redis 127.0.0.1:6379> get age "15"

redis 127.0.0.1:6379>

2.2.15 append

給指定 key 的字串值追加 value,返回新字串值的長度。例如我們向 name 的值追加一個@126.com 字串,那麼可以這樣做:

redis 127.0.0.1:6379> append name @126.com

(integer) 15

redis 127.0.0.1:6379> get name

redis 127.0.0.1:6379>

2.2.16 strlen

取指定 key 的 value 值的長度。

redis 127.0.0.1:6379> get name "HongWan_new"

redis 127.0.0.1:6379> strlen name

(integer) 11

redis 127.0.0.1:6379> get age "15"

redis 127.0.0.1:6379> strlen age

(integer) 2

redis 127.0.0.1:6379> 

2.3 hashes型別以及操作

Redis hash 是一個 string 型別的 field 和 value 的對映表.它的新增、刪除操作都是 O(1()平均)。hash 特別適合用於儲存物件。相較於將物件的每個欄位存成單個 string 型別。將一個物件儲存在 hash 型別中會佔用更少的記憶體,並且可以更方便的存取整個物件。省記憶體的原因是新建一個 hash 物件時開始是用 zipmap(又稱為 small hash)來儲存的。這個 zipmap 其實並不是 hash table,但是 zipmap 相比正常的 hash 實現可以節省不少 hash 本身需要的一些元資料儲存開銷。儘管 zipmap 的新增,刪除,查詢都是 O(n),但是由於一般物件的 field 數量都不太多。所以使用 zipmap 也是很快的,也就是說新增刪除平均還是 O(1)。如果 field 或者 value 的大小超出一定限制後,Redis 會在內部自動將 zipmap 替換成正常的 hash 實現.  這個限制可以在配置檔案中指定:

hash-max-zipmap-entries 64 #配置欄位最多 64 個

hash-max-zipmap-value 512 #配置 value 最大為 512 位元組

2.3.1 hset

設定 hash field 為指定值,如果 key 不存在,則先建立。

redis 127.0.0.1:6379> hset myhash field1 Hello

(integer) 1

redis 127.0.0.1:6379>

2.3.2 hsetnx

設定 hash field 為指定值,如果 key 不存在,則先建立。如果 field 已經存在,返回 0,nx 是not exist 的意思。

redis 127.0.0.1:6379> hsetnx myhash field "Hello"

(integer) 1

redis 127.0.0.1:6379> hsetnx myhash field "Hello"

(integer) 0

redis 127.0.0.1:6379> 

2.3.3 hmset

同時設定 hash 的多個 field。

redis 127.0.0.1:6379> hmset myhash field1 Hello field2 World

OK

redis 127.0.0.1:6379>

2.3.4 hget

獲取指定的 hash field。

redis 127.0.0.1:6379> hget myhash field1

"Hello"

redis 127.0.0.1:6379> hget myhash field2 "World"

redis 127.0.0.1:6379> hget myhash field3

(nil)

redis 127.0.0.1:6379>

由於資料庫沒有 field3,所以取到的是一個空值 nil

2.3.5 hmget

獲取全部指定的 hash filed。

redis 127.0.0.1:6379> hmget myhash field1 field2 field3

  1. "Hello"
  2. "World"
  3. (nil)

redis 127.0.0.1:6379>  

2.3.6 hincrby

指定的 hash filed 加上給定值。

redis 127.0.0.1:6379> hset myhash field3 20

(integer) 1

redis 127.0.0.1:6379> hget myhash field3 "20"

redis 127.0.0.1:6379> hincrby myhash field3 -8

(integer) 12

redis 127.0.0.1:6379> hget myhash field3

"12"

redis 127.0.0.1:6379>

2.3.7 hexists

測試指定 field 是否存在。

redis 127.0.0.1:6379> hexists myhash field1

(integer) 1

redis 127.0.0.1:6379> hexists myhash field9

(integer) 0

redis 127.0.0.1:6379> 

2.3.8 hlen

返回指定 hash 的 field 數量。

redis 127.0.0.1:6379> hlen myhash

(integer) 4

redis 127.0.0.1:6379>

通過上例可以看到 myhash 中有 4 個 field。

2.3.9 hdel

返回指定 hash 的 field 數量。

redis 127.0.0.1:6379> hlen myhash

(integer) 4

redis 127.0.0.1:6379> hdel myhash field1

(integer) 1

redis 127.0.0.1:6379> hlen myhash

(integer) 3

redis 127.0.0.1:6379>

2.3.10 hkeys

返回 hash 的所有 field。

redis 127.0.0.1:6379> hkeys myhash

  1. "field2"
  2. "field"
  3. "field3"

redis 127.0.0.1:6379> 

2.3.11 hgetall

獲取某個 hash 中全部的 filed 及 value。                                                                                                                                                                                                                                                                                                                                                                                    

redis 127.0.0.1:6379> hgetall myhash

  1. "field2"
  2. "World"
  3. "field"
  4. "Hello"
  5. "field3" 6) "12"

redis 127.0.0.1:6379>

2.3.12 havls

返回 hash 的所有 value。

redis 127.0.0.1:6379> hvals myhash

  1. "World"
  2. "Hello" 3) "12"

redis 127.0.0.1:6379> 

2.4 lists型別以及操作

list 是一個連結串列結構,主要功能是 push、pop、獲取一個範圍的所有值等等,操作中 key 理解為連結串列的名字。

Redis 的 list 型別其實就是一個每個子元素都是 string 型別的雙向連結串列。連結串列的最大長度是(2 的 32 次方)。我們可以通過 push,pop 操作從連結串列的頭部或者尾部新增刪除元素。這使得 list 既可以用作棧,也可以用作佇列。

有意思的是 list 的 pop 操作還有阻塞版本的,當我們[lr]pop 一個 list 物件時,如果 list 是空, 或者不存在,會立即返回 nil。但是阻塞版本的 b[lr]pop 可以則可以阻塞,當然可以加超時時間,超時後也會返回 nil。為什麼要阻塞版本的 pop 呢,主要是為了避免輪詢。舉個簡單的例子如果我們用 list 來實現一個工作佇列。執行任務的 thread 可以呼叫阻塞版本的 pop 去獲取任務這樣就可以避免輪詢去檢查是否有任務

存在。當任務來時候工作執行緒可以立即返回, 也可以避免輪詢帶來的延遲。說了這麼多,接下來看一下實際操作的方法吧:

2.4.1 lpush

在 key 對應 list 的頭部新增字串元素

redis 127.0.0.1:6379> lpush mylist "world"

(integer) 1

redis 127.0.0.1:6379> lpush mylist "hello" (integer) 2

redis 127.0.0.1:6379> lrange mylist 0 -1

  1. "hello"
  2. "world"

redis 127.0.0.1:6379>

2.4.2 rpush

在 key 對應 list 的尾部新增字串元素

redis 127.0.0.1:6379> rpush mylist2 "hello" (integer) 1

redis 127.0.0.1:6379> rpush mylist2 "world"

(integer) 2

redis 127.0.0.1:6379> lrange mylist2 0 -1

  1. "hello"
  2. "world"

redis 127.0.0.1:6379>

2.4.3 linsert

在 key 對應 list 的特定位置之前或之後新增字串元素

redis 127.0.0.1:6379> rpush mylist3 "hello" (integer) 1

redis 127.0.0.1:6379> rpush mylist3 "world" (integer) 2

redis 127.0.0.1:6379> linsert mylist3 before "world" "there"

(integer) 3

redis 127.0.0.1:6379> lrange mylist3 0 -1

  1. "hello"
  2. "there"
  3. "world"

redis 127.0.0.1:6379>

2.4.4 lset

設定 list 中指定下標的元素值(下標從 0 開始)

redis 127.0.0.1:6379> rpush mylist4 "one" (integer) 1

redis 127.0.0.1:6379> rpush mylist4 "two" (integer) 2

redis 127.0.0.1:6379> rpush mylist4 "three" (integer) 3

redis 127.0.0.1:6379> lset mylist4 0 "four"

OK

redis 127.0.0.1:6379> lset mylist4 -2 "five"

OK

redis 127.0.0.1:6379> lrange mylist4 0 -1

  1. "four"
  2. "five"
  3. "three"

redis 127.0.0.1:6379>

在此處我們依次插入了 one,two,three,然後將標是 0 的值設定為 four,再將下標是-2 的值設定為 five。

2.5.5 lrem

從 key 對應 list 中刪除 count 個和 value 相同的元素。count>0    時,按從頭到尾的順序刪除,具體如下:

redis 127.0.0.1:6379> rpush mylist5 "hello" (integer) 1

redis 127.0.0.1:6379> rpush mylist5 "hello" (integer) 2

redis 127.0.0.1:6379> rpush mylist5 "foo" (integer) 3

redis 127.0.0.1:6379> rpush mylist5 "hello" (integer) 4

redis 127.0.0.1:6379> lrem mylist5 2 "hello"

(integer) 2

redis 127.0.0.1:6379> lrange mylist5 0 -1

  1. "foo"
  2. "hello"

redis 127.0.0.1:6379>

count<0    時,按從尾到頭的順序刪除,具體如下:

redis 127.0.0.1:6379> rpush mylist6 "hello" (integer) 1

redis 127.0.0.1:6379> rpush mylist6 "hello" (integer) 2

redis 127.0.0.1:6379> rpush mylist6 "foo" (integer) 3

redis 127.0.0.1:6379> rpush mylist6 "hello" (integer) 4

redis 127.0.0.1:6379> lrem mylist6 -2 "hello"

(integer) 2

redis 127.0.0.1:6379> lrange mylist6 0 -1

  1. "hello"
  2. "foo"

redis 127.0.0.1:6379>

count=0 時,刪除全部,具體如下:

redis 127.0.0.1:6379> rpush mylist7 "hello" (integer) 1

redis 127.0.0.1:6379> rpush mylist7 "hello" (integer) 2

redis 127.0.0.1:6379> rpush mylist7 "foo"

(integer) 3

redis 127.0.0.1:6379> rpush mylist7 "hello" (integer) 4

redis 127.0.0.1:6379> lrem mylist7 0 "hello"

(integer) 3

redis 127.0.0.1:6379> lrange mylist7 0 -1

1) "foo"

redis 127.0.0.1:6379>

2.4.6 ltrim

保留指定 key 的值範圍內的資料

redis 127.0.0.1:6379> rpush mylist8 "one" (integer) 1

redis 127.0.0.1:6379> rpush mylist8 "two" (integer) 2

redis 127.0.0.1:6379> rpush mylist8 "three" (integer) 3

redis 127.0.0.1:6379> rpush mylist8 "four" (integer) 4

redis 127.0.0.1:6379> ltrim mylist8 1 -1

OK

redis 127.0.0.1:6379> lrange mylist8 0 -1

  1. "two"
  2. "three"
  3. "four"

redis 127.0.0.1:6379>

2.4.7 lpop

從 list 的頭部刪除元素,並返回刪除元素

redis 127.0.0.1:6379> lrange mylist 0 -1

  1. "hello"
  2. "world"

redis 127.0.0.1:6379> lpop mylist

"hello"

redis 127.0.0.1:6379> lrange mylist 0 -1

1) "world"

redis 127.0.0.1:6379>

2.4.8 rpop

從 list 的尾部刪除元素,並返回刪除元素

redis 127.0.0.1:6379> lrange mylist2 0 -1

  1. "hello"
  2. "world"

redis 127.0.0.1:6379> rpop mylist2

"world"

redis 127.0.0.1:6379> lrange mylist2 0 -1

1) "hello"

redis 127.0.0.1:6379>

2.4.9 rpoplpush

從第一個 list 的尾部移除元素並新增到第二個 list 的頭部,最後返回被移除的元素值,整個操作是原子的.如果第一個 list 是空或者不存在返回 nil

redis 127.0.0.1:6379> lrange mylist5 0 -1

  1. "three"
  2. "foo"
  3. "hello"

redis 127.0.0.1:6379> lrange mylist6 0 -1

  1. "hello"
  2. "foo"

redis 127.0.0.1:6379> rpoplpush mylist5 mylist6

"hello"

redis 127.0.0.1:6379> lrange mylist5 0 -1

  1. "three"
  2. "foo"

redis 127.0.0.1:6379> lrange mylist6 0 -1

  1. "hello"
  2. "hello"
  3. "foo"

redis 127.0.0.1:6379>

2.4.10 lindex

返回名稱為 key 的 list 中 index 位置的元素

redis 127.0.0.1:6379> lrange mylist5 0 -1

  1. "three"
  2. "foo"

redis 127.0.0.1:6379> lindex mylist5 0

"three"

redis 127.0.0.1:6379> lindex mylist5 1

"foo"

redis 127.0.0.1:6379>

2.4.11 llen

返回 key 對應 list 的長度

redis 127.0.0.1:6379> llen mylist5

(integer) 2

redis 127.0.0.1:6379>

2.5 sets型別以及操作

set 是集合,和我們數學中的集合概念相似,對集合的操作有新增刪除元素,有對多個集合求交併差等操作,操作中 key 理解為集合的名字。set 的是通過 hash table 實現的,所以新增、刪除和查詢的複雜度都是 O(1)。hash table 會隨著新增或者刪除自動的調整大小。需要注意的是調整 hash table 大小時候需要同步(獲取寫鎖)會阻塞其他讀寫操作,可能不久後就會改用跳錶(skip list)來實現,跳錶已經在 sortedset 中使用了。關於 set 集合型別除了基本的新增刪除操作,其他有用的操作還包含集合的取並集(union),交集(intersection),差集(difference)。通過這些操作可以很容易的實現   sns 中的好友推薦和 blog 的 tag 功能。下面詳細介紹 set 相關命令:

2.5.1 sadd

向名稱為 key 的 set 中新增元素

redis 127.0.0.1:6379> sadd myset "hello"

(integer) 1

redis 127.0.0.1:6379> sadd myset "world" (integer) 1

redis 127.0.0.1:6379> sadd myset "world"

(integer) 0

redis 127.0.0.1:6379> smembers myset

  1. "world"
  2. "hello"

redis 127.0.0.1:6379>

2.5.2 srem

刪除名稱為 key 的 set 中的元素 member

redis 127.0.0.1:6379> sadd myset2 "one" (integer) 1

redis 127.0.0.1:6379> sadd myset2 "two" (integer) 1

redis 127.0.0.1:6379> sadd myset2 "three" (integer) 1

redis 127.0.0.1:6379> srem myset2 "one"

(integer) 1

redis 127.0.0.1:6379> srem myset2 "four"

(integer) 0

redis 127.0.0.1:6379> smembers myset2

  1. "three"
  2. "two"

redis 127.0.0.1:6379>

 2.5.3 spop

隨機返回並刪除名稱為 key 的 set 中一個元素

redis 127.0.0.1:6379> sadd myset3 "one" (integer) 1

redis 127.0.0.1:6379> sadd myset3 "two" (integer) 1

redis 127.0.0.1:6379> sadd myset3 "three" (integer) 1

redis 127.0.0.1:6379> spop myset3

"three"

redis 127.0.0.1:6379> smembers myset3

  1. "two"
  2. "one"

redis 127.0.0.1:6379>

本例中,我們向 myset3 中添加了三個元素後,再呼叫 spop 來隨機刪除一個元素,可以看到three 元素被刪除了。

2.5.4 sdiff

返回所有給定 key 與第一個 key 的差集

redis 127.0.0.1:6379> smembers myset2

  1. "three"
  2. "two"

redis 127.0.0.1:6379> smembers myset3

  1. "two"
  2. "one"

redis 127.0.0.1:6379> sdiff myset2 myset3

1) "three"

redis 127.0.0.1:6379>

本例中,我們可以看到 myset2 中的元素與 myset3 中不同的只是 three,所以只有 three 被查出來了,而不是 three 和 one,因為 one 是 myset3 的元素。

我們也可以將 myset2 和 myset3 換個順序來看一下結果:

redis 127.0.0.1:6379> sdiff myset3 myset2

1) "one"

redis 127.0.0.1:6379>

這個結果中只顯示了,myset3 中的元素與 myset2 中不同的元素。

2.5.5 sdiffstore

返回所有給定 key 與第一個 key 的差集,並將結果存為另一個 key

redis 127.0.0.1:6379> smembers myset2 1) "three" 2) "two" redis 127.0.0.1:6379> smembers myset3 1) "two" 2) "one" redis 127.0.0.1:6379> sdiffstore myset4 myset2 myset3 (integer) 1 redis 127.0.0.1:6379> smembers myset4 1) "three" redis 127.0.0.1:6379>

2.5.6 sinter

返回所有給定 key 的交集

redis 127.0.0.1:6379> smembers myset2 1) "three" 2) "two" redis 127.0.0.1:6379> smembers myset3 1) "two" 2) "one" redis 127.0.0.1:6379> sinter myset2 myset3 1) "two

redis 127.0.0.1:6379>

通過本例的結果可以看出, myset2 和 myset3 的交集 two 被查出來了

2.5.7 sinterstore

返回所有給定 key 的交集,並將結果存為另一個 key

redis 127.0.0.1:6379> smembers myset2 1) "three" 2) "two" redis 127.0.0.1:6379> smembers myset3 1) "two" 2) "one" redis 127.0.0.1:6379> sinterstore myset5 myset2 myset3 (integer) 1 redis 127.0.0.1:6379> smembers myset5 1) "two" redis 127.0.0.1:6379>

通過本例的結果可以看出, myset2 和 myset3 的交集被儲存到 myset5 中了

2.5.8 sunion

返回所有給定 key 的並集

redis 127.0.0.1:6379> smembers myset2 1) "three" 2) "two" redis 127.0.0.1:6379> smembers myset3 1) "two" 2) "one" redis 127.0.0.1:6379> sunion myset2 myset3 1) "three" 2) "one" 3) "two" redis 127.0.0.1:6379>

通過本例的結果可以看出, myset2 和 myset3 的並集被查出來了

2.5.9 sunionstore

返回所有給定 key 的並集,並將結果存為另一個 key

redis 127.0.0.1:6379> smembers myset2 1) "three" 2) "two" redis 127.0.0.1:6379> smembers myset3

1) "two" 2) "one" redis 127.0.0.1:6379> sunionstore myset6 myset2 myset3 (integer) 3 redis 127.0.0.1:6379> smembers myset6 1) "three" 2) "one" 3) "two" redis 127.0.0.1:6379>

通過本例的結果可以看出, myset2 和 myset3 的並集被儲存到 myset6 中了

2.5.10 smove

從第一個 key 對應的 set 中移除 member 並新增到第二個對應 set 中

redis 127.0.0.1:6379> smembers myset2 1) "three" 2) "two" redis 127.0.0.1:6379> smembers myset3 1) "two" 2) "one" redis 127.0.0.1:6379> smove myset2 myset7 three (integer) 1 redis 127.0.0.1:6379> smembers myset7 1) "three" redis 127.0.0.1:6379>

通過本例可以看到,myset2 的 three 被移到 myset7 中了

2.5.11 scard

返回名稱為 key 的 set 的元素個數

redis 127.0.0.1:6379> scard myset2 (integer) 1 redis 127.0.0.1:6379

通過本例可以看到,myset2 的成員數量為 1