Redis入門教程目錄:【Redis入門教程目錄】
資料結構和內部編碼
通過這部分讓大家對Redis的五種資料結構有初步的認識,對於Redis來說,每一種資料結構都有著自己的內部編碼,而且是多種實現的,這樣Redis會在合適的場景選擇合適的內部編碼,通過OBJECT ENCODING [key]
可以參看指定key
的內部編碼。
這樣做的好處:
a. 改進內部編碼,對外的資料結構和命令沒有影響,對使用者提供黑箱模型。
b. 多種內部編碼可在不同場景下發揮各自的優勢。如:ziplist
比較節約記憶體,但是元素比較多的時候,效能會有所下降,此時Redis會將編碼自動轉換為linkedlist
,效能會有所改善。
單執行緒
瞭解Redis的單執行緒架構,有助於大家對Redis的進一步學習和排解問題。
Redis處理網路請時候的求單執行緒可以抽象成這樣,通向Redis的路只有一條,且這條路是個單車道,只容的下一輛車同時使用,而我們使用的Redis命令即為這些車輛,當我們執行多個命令的時候,只有等第一個命令執行完成了後面的命令才會執行,否則會一直處於等待狀態。 Redis單執行緒的架構需要我們注意幾點
a. 一次只執行一條命令
b. 拒絕長(慢)命令(keys、flushall、flushdb、slow lua script、mutil/exec、operate、big value)
至於為什麼單執行緒還這麼快,這裡有個原因,Redis客戶端的到Redis伺服器的網路請求採用了多路I/O複用模型(非阻塞I/O),利用
select
、poll
、epoll
可以同時監聽多個流的I/O(客戶端到伺服器的網路請求)事件的能力,在空閒的時候,會把當前執行緒阻塞掉,當有一個或者多個流有I/O
事件時,就從阻塞態中喚醒,輪訓一遍所有的流並且依次處理就緒的流。這樣就算出現有的流的I/O
因為網路原因很慢,也不會影響別的流的I/O
(非阻塞),因為是輪訓所有的流的I/O
。這裡的“多路”指的是多個網路連線,“複用”指的是複用同一個執行緒。
通用命令
Redis一些通用命令,比如刪除一個鍵、計算資料庫的大小、設定鍵的過期時間等,這些命令有很多,這裡主要介紹7
個,完整的命令大家可以參考官方文件。
- KEYS [pattern]
時間複雜度為O(N),N
為資料庫中Key
的數量。 這個命令由於時間複雜度為O(N)所以一般生產環境不使用,如果需要遍歷全部資料,可以使用Scan命令,時間複雜度為O(1)。
查詢所有符合給定模式pattern
的key
,比如說:
KEYS *
匹配資料庫中所有的key
。KEYS h?llo
匹配hello
、hallo
等key
。KEYS h*llo
匹配hllo
和haaaaaallo
等key
。KEYS h[abe]llo
匹配hallo
、hbllo
和hello
。
返回值: 符合給定模式的key
列表。
- DBSIZE
時間複雜度為O(1),計算的時候不是掃描整個表,因為Redis有個計數器,實時更新Key總數。
查詢返回當前資料庫的key
的數量。
返回值: 返回當前資料庫的key
的數量。
程式碼演示:
redis> DBSIZE
(integer) 5
redis> SET new_key "hello_moto" # 增加一個 key 試試
OK
redis> DBSIZE
(integer) 6
複製程式碼
-
EXISTS key
時間複雜度為O(1)。
檢查給定key
是否存在。
返回值: 若key
存在,返回1
,不存在返回0
。 -
DEL key [key ...]
時間複雜度為O(N),N
為被刪除的key
的數量,其中刪除單個字串型別的key
,時間複雜度為O(1)
;刪除單個列表、集合、有序集合或雜湊表型別的key
,時間複雜度為O(M)
,M
為以上資料結構內的元素數量。
刪除指定的一個或者多個key
,不存在的key
會被忽略。
返回值: 被刪除的key
的數量。 -
EXPIRE key seconds
時間複雜度為O(1)。
為給定的key
設定生存時間,當key
過期時,它會被自動刪除。
返回值: 設定成功返回1
,當key
不存在或者設定失敗的時候返回0
。 -
PERSIST key
時間複雜度為O(1)。
移除給定key
的生存時間,將這個key
轉換成持久的。
返回值: 當生存時間移除成功時,返回1
,如果key
不存在或者沒有設定生存時間,返回0
。
程式碼演示:
redis> SET mykey "Hello"
OK
redis> EXPIRE mykey 10 # 為 key 設定生存時間
(integer) 1
redis> TTL mykey
(integer) 10
redis> PERSIST mykey # 移除 key 的生存時間
(integer) 1
redis> TTL mykey
(integer) -1
複製程式碼
- TTL key
時間複雜度O(1)。
以秒為單位,返回給定key
的剩餘生存時間(TTL,time to live)。
返回值: 當key
不存在時,返回-2
,當key
存在但是沒有設定生存時間時,返回-1
,否則返回key
的剩餘生存時間。
程式碼演示:
# 不存在的 key
redis> FLUSHDB
OK
redis> TTL key
(integer) -2
# key 存在,但沒有設定剩餘生存時間
redis> SET key value
OK
redis> TTL key
(integer) -1
# 有剩餘生存時間的 key
redis> EXPIRE key 10086
(integer) 1
redis> TTL key
(integer) 10084
複製程式碼
五種資料結構
這裡介紹Redis的五種資料結構String(字串)、Hash(雜湊)、List(列表)、Set(集合)、Zset(即Sorted Set有序集合)的結構和一些命令。
字串
字串是Redis中最基礎的資料結構。
鍵值結構
字串的值雖然是字串但是可以儲存很多種型別的資料,如:簡單的字串、JSON、XML、數字、二進位制等。需要注意一點的是,Redis中字串型別的值最大能儲存512MB。
命令
- SET key value [EX seconds] [PX milliseconds] [NX|XX]
時間複雜度O(1)。
將字串值value
關聯到key
,如果key
已經持有其他值,SET
就覆寫舊值,無視型別,當SET
命令對一個帶有生存時間(TTL)的鍵進行設定之後,該鍵原有的TTL將被清除。
可選引數:
EX seconds
:將鍵的過期時間設定為seconds
秒。 執行SET key value EX seconds
的效果等同於執行SETEX key seconds value
。PX milliseconds
:將鍵的過期時間設定為milliseconds
毫秒。執行SET key value PX milliseconds
的效果等同於執行PSETEX key milliseconds value
。NX
:只在鍵不存在時,才對鍵進行設定操作。執行SET key value NX
的效果等同於執行SETNX key value
。XX
:只在鍵已經存在時,才對鍵進行設定操作。
因為
SET
命令可以通過引數來實現SETNX
、SETEX
以及PSETEX
命令的效果,所以Redis
將來的版本可能會移除並廢棄SETNX
、SETEX
和PSETEX
這三個命令。
返回值:
在Redis 2.6.12版本以前,SET
命令總是返回OK
。
從Redis 2.6.12版本開始,SET
命令只在設定操作成功完成時才返回OK
;如果命令使用了NX
或者XX
選項, 但是因為條件沒達到而造成設定操作未執行, 那麼命令將返回空批量回復(NULL Bulk Reply)。
程式碼演示:
# 使用 EX 選項
redis> SET key-with-expire-time "hello" EX 10086
OK
redis> GET key-with-expire-time
"hello"
redis> TTL key-with-expire-time
(integer) 10069
複製程式碼
- GET key
時間複雜度O(1)。
獲取與鍵key
相關聯的字串值。
返回值:
如果鍵key
不存在,那麼返回特殊值nil
;否則,返回鍵key
的值。
如果鍵key
的值並非字串型別,那麼返回一個錯誤,因為GET
命令只能用於字串值。
程式碼演示:
redis> GET db
(nil)
redis> SET db redis
OK
redis> GET db
"redis"
複製程式碼
- DEL key [key ...]
時間複雜度為O(N),N
為被刪除的key
的數量,其中刪除單個字串型別的key
,時間複雜度為O(1)
;刪除單個列表、集合、有序集合或雜湊表型別的key
,時間複雜度為O(M)
,M
為以上資料結構內的元素數量。
刪除指定的一個或者多個key
,不存在的key
會被忽略。
返回值: 被刪除的key
的數量。
程式碼演示:
# 同時刪除多個 key
redis> SET name "redis"
OK
redis> SET type "key-value store"
OK
redis> SET website "redis.com"
OK
redis> DEL name type website
(integer) 3
複製程式碼
- MSET key value [key value ...]
時間複雜度O(N),其中N
為被設定的鍵數量。
同時為多個鍵設定值。如果某個給定鍵已經存在,那麼MSET
將使用新值去覆蓋舊值,如果這不是你所希望的效果,請考慮使用MSETNX
命令,這個命令只會在所有給定鍵都不存在的情況下進行設定。MSET
是一個原子性(atomic) 操作,所有給定鍵都會在同一時間內被設定,不會出現某些鍵被設定了但是另一些鍵沒有被設定的情況。
返回值:MSET
命令總是返回OK
。
程式碼演示:
redis> MSET date "2012.3.30" time "11:00 a.m." weather "sunny"
OK
redis> MGET date time weather
1) "2012.3.30"
2) "11:00 a.m."
3) "sunny"
複製程式碼
- MSETNX key value [key value ...]
時間複雜度O(N),其中N
為被設定的鍵數量。
當且僅當所有給定鍵都**不存在時,為所有給定鍵設定值。即使只有一個給定鍵已經存在,MSETNX
命令也會拒絕執行對所有鍵的設定操作。MSETNX
是一個原子性(atomic) 操作,所有給定鍵要麼就全部都被設定,要麼就全部都不設定,不可能出現第三種狀態。
返回值: 當所有給定鍵都設定成功時,命令返回1
;如果因為某個給定鍵已經存在而導致設定未能成功執行,那麼命令返回0
。
程式碼演示:
redis> MSETNX rmdbs "MySQL" nosql "MongoDB" key-value-store "redis"
(integer) 1
redis> MGET rmdbs nosql key-value-store
1) "MySQL"
2) "MongoDB"
3) "redis"
複製程式碼
- MGET key [key ...]
時間複雜度O(N),其中N
為給定鍵的數量。
返回給定的一個或多個字串鍵的值。如果給定的字串鍵裡面,有某個鍵不存在,那麼這個鍵的值將以特殊值nil
表示。
返回值:MGET
命令將返回一個列表,列表中包含了所有給定鍵的值。
程式碼演示:
redis> SET redis redis.com
OK
redis> SET mongodb mongodb.org
OK
redis> MGET redis mongodb
1) "redis.com"
2) "mongodb.org"
redis> MGET redis mongodb mysql # 不存在的 mysql 返回 nil
1) "redis.com"
2) "mongodb.org"
3) (nil)
複製程式碼
-
N次GET和一次MGET對比
如果我們把
總所周知,Redis採用的是客戶端-伺服器方式,即在一次round trip中,客戶端傳送一條命令,伺服器解析命令並執行,然後向客戶端返回結果,如果執行N
條命令,就是N
個請求N
次執行N
個返回N
條命令都放在一個請求中,一次請求多個執行一個返回,那麼就可以大大的降低網路時間的開銷,這個也就是Redis的pipline -
N次SET和一次MSET對比
同7
雜湊
Redis的雜湊是鍵值對的集合,是字串欄位和字串值之間的對映。
鍵值結構
Hash
資料結構即資料儲存為field
、value
的格式儲存
field
、value
看成一對鍵值對結構
命令
- HSET key field value
時間複雜度O(1)。
將雜湊表key
中域field
的值設定為value
,如果給定的雜湊表不存在,那麼一個新的雜湊表將被建立並執行HSET
操作,如果域field
已存在於雜湊表中,那麼它的舊值將被新值value
覆蓋。
返回值: 當HSET
命令在雜湊表中新建立field
域併成功為它設定值時,命令返回1
;如果域field
已經存在於雜湊表,並且HSET
命令成功使用新值覆蓋了它的舊值,那麼命令返回0
。
程式碼演示:
redis> HSET website google "www.g.cn"
(integer) 1
redis> HGET website google
"www.g.cn"
複製程式碼
- HGET key field
時間複雜度O(1)。
返回雜湊表中給定域的值。
返回值:HGET
命令在預設情況下返回給定域的值,如果給定域不存在於雜湊表中,又或者給定的雜湊表並不存在,那麼命令返回nil
。 程式碼演示:
redis> HSET homepage redis redis.com
(integer) 1
redis> HGET homepage redis
"redis.com"
複製程式碼
- HGETALL key
時間複雜度O(N),N
為雜湊表的大小,謹慎用。
返回雜湊表的所有的域和值,在返回值裡,緊跟每個域(field name)之後是域的值(value),所以返回值的長度是雜湊表大小的兩倍。
返回值: 以列表形式返回雜湊表的域和域的值,若key
不存在,返回空列表。 程式碼演示:
redis> HSET people jack "Jack Sparrow"
(integer) 1
redis> HSET people gump "Forrest Gump"
(integer) 1
redis> HGETALL people
1) "jack" # 域
2) "Jack Sparrow" # 值
3) "gump"
4) "Forrest Gump"
複製程式碼
- HDEL key field [field ...]
時間複雜度O(N),N
為要刪除的域的數量。
刪除雜湊表key
中的一個或多個指定域,不存在的域將被忽略。
返回值: 被成功移除的域的數量,不包括被忽略的域。
程式碼演示:
# 測試資料
redis> HGETALL abbr
1) "a"
2) "apple"
3) "b"
4) "banana"
5) "c"
6) "cat"
7) "d"
8) "dog"
# 刪除單個域
redis> HDEL abbr a
(integer) 1
# 刪除不存在的域
redis> HDEL abbr not-exists-field
(integer) 0
# 刪除多個域
redis> HDEL abbr b c
(integer) 2
redis> HGETALL abbr
1) "d"
2) "dog"
複製程式碼
- HMSET key field value [field value ...]
時間複雜度O(N),N
為field-value
對的數量。
同時將多個field-value
(域-值)對設定到雜湊表key
中,此命令會覆蓋雜湊表中已存在的域,如果key
不存在,一個空雜湊表被建立並執行HMSET
操作。
返回值: 如果命令執行成功,返回OK
,當key
不是雜湊表(hash)型別時,返回一個錯誤。 程式碼演示:
redis> HMSET website google www.google.com yahoo www.yahoo.com
OK
redis> HGET website google
"www.google.com"
redis> HGET website yahoo
"www.yahoo.com"
複製程式碼
- HMGET key field [field ...]
時間複雜度O(N),N
為給定域的數量。
返回雜湊表key
中,一個或多個給定域的值,如果給定的域不存在於雜湊表,那麼返回一個nil
值,因為不存在的key
被當作一個空雜湊表來處理,所以對一個不存在的key
進行HMGET
操作將返回一個只帶有nil
值的表。
返回值: 一個包含多個給定域的關聯值的表,表值的排列順序和給定域引數的請求順序一樣。
程式碼演示:
redis> HMSET pet dog "doudou" cat "nounou" # 一次設定多個域
OK
redis> HMGET pet dog cat fake_pet # 返回值的順序和傳入引數的順序一樣
1) "doudou"
2) "nounou"
3) (nil) # 不存在的域返回nil值
複製程式碼
- N次HGET和一次HMGET對比
參考字串的N
次GET
和一次MGET
對比,大概相同
列表
列表用於儲存多個有序的字串,列表是一種比較靈活的資料結構,可以充當棧和佇列的角色。
鍵值結構
列表的value
其實是一個雙向連結串列,可以在連結串列的兩頭插入或者刪除元素
命令
- LPUSH key value [value ...]
時間複雜度O(1)。
將一個或多個值value
插入到列表key
的表頭,如果有多個value
值,那麼各個value
值按從左到右的順序依次插入到表頭:比如說,對空列表mylist
執行命令LPUSH mylist a b c
,列表的值將是c b a
,這等同於原子性地執行LPUSH mylist a
、LPUSH mylist b
和LPUSH mylist c
三個命令,如果key
不存在,一個空列表會被建立並執行LPUSH
操作,當key
存在但不是列表型別時,返回一個錯誤。
返回值: 執行LPUSH
命令後,列表的長度。 程式碼演示:
# 加入單個元素
redis> LPUSH languages python
(integer) 1
# 加入重複元素
redis> LPUSH languages python
(integer) 2
redis> LRANGE languages 0 -1 # 列表允許重複元素
1) "python"
2) "python"
# 加入多個元素
redis> LPUSH mylist a b c
(integer) 3
redis> LRANGE mylist 0 -1
1) "c"
2) "b"
3) "a"
複製程式碼
- RPUSH key value [value ...]
時間複雜度O(1)。
將一個或多個值value
插入到列表key
的表尾(最右邊),如果有多個value
值,那麼各個value
值按從左到右的順序依次插入到表尾:比如說,對空列表mylist
執行命令RPUSH mylist a b c
,列表的值將是c b a
,這等同於原子性地執行RPUSH mylist a
、RPUSH mylist b
和RPUSH mylist c
三個命令,如果key
不存在,一個空列表會被建立並執行RPUSH
操作,當key
存在但不是列表型別時,返回一個錯誤。
返回值: 執行RPUSH
命令後,列表的長度。 程式碼演示:
# 新增單個元素
redis> RPUSH languages c
(integer) 1
# 新增重複元素
redis> RPUSH languages c
(integer) 2
redis> LRANGE languages 0 -1 # 列表允許重複元素
1) "c"
2) "c"
# 新增多個元素
redis> RPUSH mylist a b c
(integer) 3
redis> LRANGE mylist 0 -1
1) "a"
2) "b"
3) "c"
複製程式碼
- LPOP key
時間複雜度O(1)。
移除頭元素並返回列表key
新的頭元素。
返回值: 列表的頭元素。當key
不存在時,返回nil
。 程式碼演示:
# 加入單個元素
redis> LLEN course
(integer) 0
redis> RPUSH course algorithm001
(integer) 1
redis> RPUSH course c++101
(integer) 2
redis> LPOP course # 移除頭元素
"algorithm001"
複製程式碼
- RPOP key
時間複雜度O(1)。
移除尾元素並返回列表key
新的尾元素。
返回值: 列表的尾元素。當key
不存在時,返回nil
。 程式碼演示:
redis> RPUSH mylist "one"
(integer) 1
redis> RPUSH mylist "two"
(integer) 2
redis> RPUSH mylist "three"
(integer) 3
redis> RPOP mylist # 返回被彈出的元素
"three"
redis> LRANGE mylist 0 -1 # 列表剩下的元素
1) "one"
2) "two"
複製程式碼
- LINDEX key index
時間複雜度O(N),N
為到達下標index
過程中經過的元素數量。因此,對列表的頭元素和尾元素執行LINDEX
命令,複雜度為O(1)。
返回列表key
中,下標為index
的元素,下標(index)引數start
和stop
都以0
為底,也就是說,以0
表示列表的第一個元素,以1
表示列表的第二個元素,以此類推,你也可以使用負數下標,以-1
表示列表的最後一個元素,-2
表示列表的倒數第二個元素,以此類推,如果key
不是列表型別,返回一個錯誤。
返回值: 列表中下標為index
的元素。如果index
引數的值不在列表的區間範圍內(out of range),返回nil
。
程式碼演示:
redis> LPUSH mylist "World"
(integer) 1
redis> LPUSH mylist "Hello"
(integer) 2
redis> LINDEX mylist 0
"Hello"
redis> LINDEX mylist -1
"World"
redis> LINDEX mylist 3 # index不在 mylist 的區間範圍內
(nil)
複製程式碼
- LINSERT key BEFORE|AFTER pivot value
時間複雜度O(N),N
為尋找pivot
過程中經過的元素數量。
將值value
插入到列表key
當中,位於值pivot
之前或之後,當pivot
不存在於列表key
時,不執行任何操作,當key
不存在時,key
被視為空列表,不執行任何操作,如果key
不是列表型別,返回一個錯誤。
返回值: 如果命令執行成功,返回插入操作完成之後,列表的長度。如果沒有找到pivot
,返回-1
。如果key
不存在或為空列表,返回0
。
程式碼演示:
redis> RPUSH mylist "Hello"
(integer) 1
redis> RPUSH mylist "World"
(integer) 2
redis> LINSERT mylist BEFORE "World" "There"
(integer) 3
redis> LRANGE mylist 0 -1
1) "Hello"
2) "There"
3) "World"
# 對一個非空列表插入,查詢一個不存在的 pivot
redis> LINSERT mylist BEFORE "go" "let's"
(integer) -1 # 失敗
# 對一個空列表執行 LINSERT 命令
redis> EXISTS fake_list
(integer) 0
redis> LINSERT fake_list BEFORE "nono" "gogogog"
(integer) 0 # 失敗
複製程式碼
集合
Redis的Set
是String
型別的無序集合,這裡的集合也就是我們小學都接觸到的集合,可以求交集、並集、差集等。集合成員是唯一的,這就意味著集合中不能出現重複的資料。集合是通過雜湊表實現的,所以新增,刪除,查詢的複雜度都是 O(1)。
鍵值結構
左邊為key
,是字串型別。右邊為value
,可以將一些字串進行一些組合,是集合型別。Redis中的集合型別還支援集合之間的操作,這與Redis中的其他資料結構是不同的,Redis可以對兩個集合進行操作,取兩個集合的交集,並集,差集以及對稱差集等。
命令
- SADD key member [member …]
時間複雜度O(N),N
為被新增的元素的數量。
將一個或多個member
元素加入到集合key
當中,已經存在於集合的member
元素將被忽略,假如key
不存在,則建立一個只包含member
元素作成員的集合,當key
不是集合型別時,返回一個錯誤。
返回值: 被新增到集合中的新元素的數量,不包括被忽略的元素。
程式碼演示:
# 新增單個元素
redis> SADD bbs "discuz.net"
(integer) 1
# 新增重複元素
redis> SADD bbs "discuz.net"
(integer) 0
# 新增多個元素
redis> SADD bbs "tianya.cn" "groups.google.com"
(integer) 2
redis> SMEMBERS bbs
1) "discuz.net"
2) "groups.google.com"
3) "tianya.cn"
複製程式碼
- SPOP key [count]
時間複雜度O(1)。
隨機移除count
個元素並返回被移除的元素。
返回值: 被移除的隨機元素。當key
不存在或key
是空集時,返回nil
。
程式碼演示:
redis> SMEMBERS db
1) "MySQL"
2) "MongoDB"
3) "Redis"
redis> SPOP db
"Redis"
redis> SMEMBERS db
1) "MySQL"
2) "MongoDB"
redis> SPOP db
"MySQL"
redis> SMEMBERS db
1) "MongoDB"
複製程式碼
- SREM key member [member …]
時間複雜度O(N),N
為給定member
元素的個數。
移除集合key
中的一個或多個member
元素,不存在的member
元素會被忽略,當key
不是集合型別,返回一個錯誤。
返回值: 被成功移除的元素的個數,不包括被忽略的元素。
程式碼演示:
# 測試資料
redis> SMEMBERS languages
1) "c"
2) "lisp"
3) "python"
4) "ruby"
# 移除單個元素
redis> SREM languages ruby
(integer) 1
# 移除不存在元素
redis> SREM languages non-exists-language
(integer) 0
# 移除多個元素
redis> SREM languages lisp python c
(integer) 3
redis> SMEMBERS languages
(empty list or set)
複製程式碼
- SMEMBERS key
時間複雜度O(N),N
為集合的基數。
返回集合key
中的所有成員,不存在的key
被視為空集合。
返回值: 集合中的所有成員。
程式碼演示:
# key 不存在或集合為空
redis> EXISTS not_exists_key
(integer) 0
redis> SMEMBERS not_exists_key
(empty list or set)
# 非空集合
redis> SADD language Ruby Python Clojure
(integer) 3
redis> SMEMBERS language
1) "Python"
2) "Ruby"
3) "Clojure"
複製程式碼
有序集合
Redis有序集合和集合一樣也是String
型別元素的集合,且不允許重複的成員。不同的是每個元素都會關聯一個double
型別的分數。Redis正是通過分數來為集合中的成員進行從小到大的排序。有序集合的成員是唯一的,但分數(score)卻可以重複。集合是通過雜湊表實現的,所以新增,刪除,查詢的複雜度都是O(1)。
鍵值結構
有序集合的value
包括score
和value
兩部分,其中score
表示分值用來排序的
命令
- ZADD key [NX|XX] [CH] [INCR] score member [score member …]
時間複雜度O(M*log(N)),N
是有序集的基數,M
為成功新增的新成員的數量。
將一個或多個member
元素及其score
值加入到有序集key
當中。如果某個member
已經是有序集的成員,那麼更新這個member
的score
值,並通過重新插入這個member
元素,來保證該member
在正確的位置上。score
值可以是整數值或雙精度浮點數。如果key
不存在,則建立一個空的有序集並執行ZADD
操作。當key
存在但不是有序集型別時,返回一個錯誤。
Redis 3.0.2 為ZADD
命令新增了NX
、XX
、CH
、INCR
四個選項:
NX
:member
必須不存在,才可以設定成功,用於新增。XX
:member
必須存在,才可以設定成功,用於更新。CH
:返回此次操作後,有序集合元素和分數發生變化的個數。INCR
:對score
做增加,相當於ZINCRBY
。 返回值: 被成功新增的新成員的數量,不包括那些被更新的、已經存在的成員。
程式碼演示:
redis> ZADD ztest 100 java 99 python 80 go 120 kotlin
(integer) 4
# 檢視有序集合內所有元素並且按分數排序
coderknock> ZRANGE ztest 0 -1 WITHSCORES
1) "go"
2) "80"
3) "python"
4) "99"
5) "java"
6) "100"
7) "kotlin"
8) "120"
# 選項填寫在 key 後面,位置不能錯誤
redis> ZADD ztest 100 java 99 python 80 go 120 kotlin CH
(error) ERR syntax error
redis> ZADD CH ztest 100 java 99 python 80 go 120 kotlin
(error) ERR syntax error
# 下面兩個語句進行了對比,如果不加 CH 顯示的數量不包括更新和已經存在的。
redis> ZADD ztest CH 100 java 99 python 80 go 121 kotlin
(integer) 1
redis> ZADD ztest 100 java 99 python 80 go 120 kotlin
(integer) 0
複製程式碼
- ZREM key member [member …]
時間複雜度O(M*log(N)),N
是有序集的基數,M
為成功移除的成員的數量。
移除有序集key
中的一個或多個成員,不存在的成員將被忽略,當key
存在但不是有序集型別時,返回一個錯誤。
返回值: 被成功移除的成員的數量,不包括被忽略的成員。
程式碼演示:
# 測試資料
redis> ZRANGE page_rank 0 -1 WITHSCORES
1) "bing.com"
2) "8"
3) "baidu.com"
4) "9"
5) "google.com"
6) "10"
# 移除單個元素
redis> ZREM page_rank google.com
(integer) 1
redis> ZRANGE page_rank 0 -1 WITHSCORES
1) "bing.com"
2) "8"
3) "baidu.com"
4) "9"
# 移除多個元素
redis> ZREM page_rank baidu.com bing.com
(integer) 2
redis> ZRANGE page_rank 0 -1 WITHSCORES
(empty list or set)
# 移除不存在元素
redis> ZREM page_rank non-exists-element
(integer) 0
複製程式碼