Redis常用命令詳細介紹(摘抄)
Redis常用命令詳細介紹
一、字串
字串鍵是Redis最基本的鍵值對型別,將一個單獨的鍵和一個單獨的值關聯起來。通過字串鍵,不僅可以儲存和讀取字串,如果輸入能被解釋為整數和浮點數,還能執行自增或自減操作。
1、SET:設定字串鍵的值
命令 | SET key value [EX seconds|PX milliseconds] [NX|XX] |
---|---|
效果 | 為字串鍵設定值,如果字串鍵不存在,建立這個字串鍵;如果已經存在,直接更新值。 EX和PX選項設定鍵的生存時間(以秒或毫秒為單位)。當生存時間消耗殆盡後,這個鍵就會被移除。 NX和XX選項決定了是隻進行建立操作還是更新操作。(NX代表not exists) |
返回值 | 如果不使用NX和XX選項,返回OK。 若給定NX,僅當key不存在的情況下執行操作並返回OK,否則返回nil表示操作失敗。若給定XX,僅當key存在的情況下執行操作覆蓋舊值並返回OK,否則返回nil表示操作失敗。 |
注意:同樣可以設定字串鍵值的還有SETNX、SETEX、PSETEX,它們顧名思義很好理解作用,例如SETNX相當於給定了NX選項的SET命令。由於SET本身已經足夠全能,推薦都使用SET命令,其他的命令在遙遠的未來有可能被移除掉。
2、GET:獲取字串鍵的值
命令 | GET key |
---|---|
效果 | 根據字串鍵獲取值 |
返回值 | 鍵對應的值。如果鍵不存在,返回nil。 |
3、GETSET:獲取舊值並設定新值
命令 | GETSET key value |
---|---|
效果 | 先獲取字串鍵當前值,再設定新值,最後返回舊值 |
返回值 | 返回舊值。如果鍵不存在,返回nil。 |
4、MSET、MSETNX、MGET:批量設定獲取值
命令 | MSET key1 value1 [key2 value2 ...] |
---|---|
效果 | 一次為多個字串鍵分別設定值 |
返回值 | 返回OK |
相比SET,一條MSET在代替多條SET的同時只需要客戶端和伺服器進行一次通訊,從而提高了執行效率。
如果你不想覆蓋已經存在的值,使用MSETNX:
命令 | MSETNX key1 value1 [key2 value2 ...] |
---|---|
效果 | 僅當所有key都不存在才一次設定多個鍵值對,否則放棄操作 |
返回值 | 如果所有key都不存在,操作成功,返回1;如果有至少一個key有值,放棄操作,返回0。 |
既然能批量寫,自然也能批量讀:
命令 | MGET key1 [key2 ...] |
---|---|
效果 | 一次獲取多個字串鍵的值 |
返回值 | 返回一個列表,按鍵的順序排列各個值 |
redis> MSET a food b water
OK
redis> MGET b a c
1) "water"
2) "food"
3) (nil)
5、STRLEN:獲取值的位元組長度
命令 | STRLEN key |
---|---|
效果 | 獲取字串值的位元組長度 |
返回值 | 返回一個整數。如果字串鍵不存在,返回0。 |
6、GETRANGE、SETRANGE:根據索引獲取或設定內容
每個字串值都可以通過索引獲取對應的位元組,既可以使用正數索引,也可以使用負數索引(末位為-1,倒數第二個位元組為-2,以此類推)
命令 | GETRANGE key start end |
---|---|
效果 | 獲取值在[start, end]索引範圍的子串 |
返回值 | 返回子串。如果鍵不存在,或者兩個索引都超過了範圍,返回空字串。 |
命令 | SETRANGE key index substr |
---|---|
效果 | 將值從指定index處開始替換。如果index超過了值本身的範圍,空餘部分使用\x00填充 |
返回值 | 返回替換後值的長度 |
7、APPEND:追加新內容到值的末尾
命令 | APPEND key suffix |
---|---|
效果 | 將suffix的內容追加到值的末尾。如果鍵不存在,相當於SET |
返回值 | 返回操作後值的長度 |
8、INCRBY、DECRBY、INCR、DECR、INCRBYFLOAT:對整數和浮點數執行加法和減法操作
如果儲存的字串鍵的值可以被解釋為整數或浮點數,則可以執行加法和減法操作,包括:
1、對於整數而言,必須位於64位長度的有符號整數的範圍內,為-9223372036854775808~9223372036854775807之間。
2、可以用C語言的long double型別儲存的浮點數。
下表列出了一些情形:
值 | 解釋值 |
---|---|
12345 | 整數 |
+888 | 整數 |
-999 | 整數 |
3.14 | 浮點數 |
+2.718 | 浮點數 |
-6.66 | 浮點數 |
-.5 | 浮點數 |
5. | 整數 |
12345678901234567890 | 這個整數太大了,超過了64位有符號整數的範圍,故為字串 |
1.23e4 | Reids無法解釋科學計數法,所以是字串 |
123abc | 字串 |
INCRBY和DECRBY可以對整數值執行加法和減法操作。
命令 | INCRBY key increment |
---|---|
效果 | 為整數加上指定的整數增量,更新之。如果值或增量是浮點數等非整數會報錯。如果鍵不存在,先初始化值為0再執行操作。 |
返回值 | 返回運算後的結果 |
increment可以為負整數,這意味著INCR可以執行減法操作,同樣DECR可以執行加法操作。
INCR和DECR是INCRBY和DECRBY的簡化版,用於對整數值自增1或自減1。
命令 | INCR key |
---|---|
效果 | 整數值自增1。如果值是浮點數等非整數會報錯。如果鍵不存在,先初始化值為0再執行操作。 |
返回值 | 返回運算後的結果 |
以上的四個命令只能用於整數的加減運算,加數或被加數為浮點數都會導致Redis返回錯誤。使用INCRBYFLOAT可以執行整數和浮點數的加減法操作。(沒有DECRBYFLOAT)
命令 | INCRBYFLOAT key increment |
---|---|
效果 | 執行浮點數加減法,更新之。值和increment都可以是整數或浮點數,甚至形如1.23e4這樣用指數表示。如果鍵不存在,先初始化值為0再執行操作。如果執行結果可以表示為整數,則以整數形式儲存。最多保留小數點後17位數字。 |
返回值 | 返回運算後的結果 |
9、總結
- SET、GET、GETSET設定或獲取字串鍵,其中SET包含了豐富的選項,既可以決定是建立還是更新,也可以設定生存時間。這幾個命令都只能操作一個鍵值對。
- MSET、MSETNX、MGET批量操作多個鍵值對,只需要客戶端和伺服器進行一次通訊,從而提高了執行效率。
- 字串值既可以使用正數索引,也可以使用負數索引。
- GETRANGE、SETRANGE、APPEND可以獲取和設定字串值的部分。
- 如果值可以被解釋為數值,可以對數值進行增減操作,如INCRBY、DECRBY、INCR、DECR、INCRBYFLOAT。
- 獲取字串值的位元組長度:STRLEN
二、雜湊(hash)
Redis的雜湊鍵將一個鍵和一個雜湊關聯起來,在雜湊中可以為任意多個欄位(field)分別設定值。比起字串鍵,雜湊鍵能將多個有關聯的資料打包起來儲存。
1、HSET、HSETNX、HGET:設定值或讀取值
命令 | HSET hash field1 value1 [field2 value2...] |
---|---|
效果 | 為一個或多個指定欄位設定值。根據欄位是否存在於雜湊進行建立或覆蓋操作。 |
返回值 | 新增的欄位的數量。這意味著如果全部是覆蓋,將返回0 |
在Redis 4.0.0之前,HSET只能一次給一個欄位設定值。
相比SET,HSET可以一次設定多個值,但沒有諸如NX的選項,此時可以使用HSETNX:
命令 | HSETNX hash field value |
---|---|
效果 | 只在欄位不存在的情況下為其設定值 |
返回值 | 如果欄位不存在,設定成功並返回1,反之不執行操作,返回0 |
沒有HSETEX這樣的命令,這是因為雜湊的生存時間是對整個雜湊而言的,不能單獨為某個欄位設定生存時間。
獲取某個欄位的值,用HGET:
命令 | HGET hash field |
---|---|
效果 | 獲取欄位的值 |
返回值 | 返回欄位的值。如果雜湊或欄位不存在,返回nil。 |
redis> HSET hash1 f1 hello f2 world
2
redis> HSET hash1 f2 World f1 Hello
0
redis> HSETNX hash1 f2 WORLD
0
redis> HGET hash1 f2
"World"
redis> HGET hash1 f
(nil)
2、HMGET:批量操作
命令 | HMGET hash field1 [field2 ...] |
---|---|
效果 | 一次獲取多個欄位的值 |
返回值 | 返回一個數組 |
類似於MSET,雜湊也提供了批量設定欄位的命令HMSET,不過自從Redis 4.0.0增強了HSET之後,官方建議不要繼續使用功能重複的HMSET。(HMSET:明明是我先...)
3、HKEYS、HVALS、HGETALL:獲取所有欄位和值
前面的命令必須指定欄位才能獲取值,那麼有沒有直接獲取整個雜湊所有欄位和值的命令呢?您好,有的。
命令 | HKEYS hash |
---|---|
效果 | 獲取雜湊的所有欄位 |
返回值 | 以列表返回雜湊的所有欄位。如果雜湊不存在,返回空列表 |
命令 | HVALS hash |
---|---|
效果 | 獲取雜湊的所有值 |
返回值 | 以列表返回雜湊的所有值。如果雜湊不存在,返回空列表 |
命令 | HGETALL hash |
---|---|
效果 | 獲取雜湊所有欄位和值 |
返回值 | 以列表返回雜湊的所有欄位和值。如果雜湊不存在,返回空列表 |
redis> HKEYS hash1
1) "f1"
2) "f2"
redis> HVALS hash1
1) "Hello"
2) "World"
redis> HGETALL hash1
1) "f1"
2) "Hello"
3) "f2"
4) "World"
4、HSTRLEN、HLEN:值的位元組長度和雜湊的欄位數量
命令 | HSTRLEN hash field |
---|---|
效果 | 獲取欄位值的位元組長度 |
返回值 | 返回欄位值的位元組長度。如果雜湊或欄位不存在,返回0 |
命令 | HLEN hash |
---|---|
效果 | 獲取雜湊包含的欄位數量 |
返回值 | 返回雜湊包含的欄位數量。如果雜湊不存在,返回0 |
5、HEXISTS、HDEL:欄位是否存在,刪除欄位
命令 | HEXISTS hash field |
---|---|
效果 | 檢查給定欄位是否存在於雜湊中 |
返回值 | 如果雜湊包含給定欄位,返回1,否則返回0。如果雜湊不存在,返回0 |
命令 | HDEL hash field1 [field2 ...] |
---|---|
效果 | 刪除一個或多個給定欄位。本來就不存在的欄位會被忽略。 |
返回值 | 返回刪除成功的欄位的數量。如果雜湊不存在,返回0 |
注意:HDEL刪除的是欄位,如要刪除整個雜湊,使用DEL命令(後面會講到)。
redis> HGETALL hash1
1) "f1"
2) "Hello"
3) "f2"
4) "World"
redis> HDEL hash1 f2 f3
(integer) 1
redis> HKEYS hash1
1) "f1"
6、HINCRBY、HINCRBYFLOAT:對欄位儲存的數字值執行加減操作
命令 | HINCRBY hash field increment |
---|---|
效果 | 對整數值執行加法或減法操作,更新之 |
返回值 | 返回操作結果 |
命令 | HINCRBYFLOAT hash field increment |
---|---|
效果 | 執行浮點數加法或減法操作,更新之 |
返回值 | 返回操作結果 |
Redis沒有提供HINCR、HDECRBY之類的命令。
7、雜湊與字串
由於一個雜湊中可以包含多個欄位,它天然地適合多項關聯資料的存放,而只需要在資料庫中建立一個雜湊鍵。雖然用字串鍵也能達到類似的效果,但更多的鍵將帶來更大的開銷。
另一方面,字串鍵的命令比雜湊更加豐富,功能更加強大。比如字串鍵支援GETRANGE、APPEND命令,這些更加精細的操作是雜湊不具備的,後面還會說到對字串鍵的值按位進行讀寫,即Bitmap。此外,雜湊也無法單獨對某個欄位設定過期時間,一旦某個雜湊鍵過期,它儲存的所有欄位和值都將消失,而使用字串鍵就不會有這樣的顧慮。
在命令上,二者都有很多相似的命令,列舉如下:
字串 | 雜湊 | 對比 |
---|---|---|
SET | HSET | 給字串鍵/雜湊的欄位設定值 |
SETNX | HSETNX | 條件是字串鍵/欄位不存在 |
MSET | HSET、HMSET | 為多個字串鍵/雜湊的多個欄位設定值 |
GET | HGET | 獲取字串鍵/雜湊的欄位的值 |
MGET | HMGET | 獲取多個字串鍵/雜湊的多個欄位的值 |
STRLEN | HSTRLEN | 獲取字串值/欄位值的位元組長度 |
INCRBY | HINCRBY | 對字串值/欄位值進行整數加減操作 |
INCRBYFLOAT | HINCRBYFLOAT | 對字串值/欄位值進行浮點數加減操作 |
EXISTS | HEXISTS | 檢查鍵/欄位是否存在於資料庫/雜湊,EXISTS後面會講 |
DEL | HDEL | 從資料庫/雜湊中刪除鍵/欄位,DEL後面會講 |
此外,雜湊還有:
- HLEN獲取雜湊的欄位數。
- HKEYS、HVALS、HGETALL列出雜湊的所有欄位。
三、列表(list)
Redis的列表是一種線性的有序結構,按照元素被推入的順序儲存元素,當然也可以通過索引進行訪問。
1、LPUSH、LPUSHX、RPUSH、RPUSHX:將元素推入左端或右端
命令 | LPUSH list element1 [element2 ...] |
---|---|
效果 | 將元素推入列表左端。如果推入多個元素,則從左往右依次將所有元素推入左端 |
返回值 | 返回推入操作後列表的元素數量 |
命令 | LPUSHX list element1 [element2 ...] |
---|---|
效果 | 只對已存在的列表執行推入操作 |
返回值 | 返回推入操作後列表的元素數量。如果列表鍵不存在,不執行推入操作,返回0 |
redis> LPUSHX list1 3 4 5
(integer) 0
類似地,RPUSH、RPUSHX將元素推入列表右端。
2、LPOP、RPOP:彈出元素
命令 | LPOP list |
---|---|
效果 | 彈出列表最左端的元素 |
返回值 | 返回彈出的元素。如果列表不存在,返回nil |
類似地,RPOP從右端彈出元素。
注意:可以一次推入多個,但是隻能一次彈出一個。如果想安全彈出多個,可以使用事務。
3、RPOPLPUSH:將右端彈出的元素推入左端
命令 | RPOPLPUSH source destination |
---|---|
效果 | 先使用RPOP將源列表最右端元素彈出,然後使用LPUSH將被彈出的元素推入目標列表左端。源列表和目標列表可以相同,藉此可以構造一個迴圈的列表 |
返回值 | 返回該元素。如果源列表不存在,放棄執行彈出和推入,返回nil |
注:沒有LPOPRPUSH命令。
4、LINDEX、LRANGE:獲取指定索引和索引範圍上的元素
類似於字串的索引,列表包含的每個元素也有對應的正數索引和負數索引。
命令 | LINDEX list index |
---|---|
效果 | 獲取指定索引上的元素 |
返回值 | 返回指定索引上的元素。如果列表不存在或索引越界,返回nil |
命令 | LRANGE list start stop |
---|---|
效果 | 獲取[start, stop]索引範圍上的元素 |
返回值 | 返回指定範圍內的所有元素。如果列表不存在,或兩個索引都越界,或start大於stop,返回空列表。如果只有start越界,start會被修正為0,然後返回對應範圍的元素;同理如果stop越界,修正為-1 |
redis> RPUSH list1 1 2 3
(integer) 3
redis> LRANGE list1 0 -1
1) "1"
2) "2"
3) "3"
redis> LINDEX list1 2
"3"
redis> LINDEX list1 3
(nil)
redis> LRANGE list1 2 5
1) "3"
5、LSET:根據索引設定新元素
命令 | LSET list index element |
---|---|
效果 | 為指定索引設定新元素 |
返回值 | 返回OK。如果列表不存在或給定索引越界,返回錯誤 |
注意:不同於LINDEX,如果LSET的索引越界,將返回錯誤。
6、LINSERT:將元素插入列表
命令 | LINSERT list BEFORE|AFTER target_element new_element |
---|---|
效果 | 將新元素插入目標元素的前面或後面。如果目標元素在列表中有多個,只對從左往右第一個目標元素執行操作 |
返回值 | 返回插入後列表的長度。如果目標元素不存在,返回-1 |
redis> LPUSH list2 hello world hello
(integer) 3
redis> LINSERT list2 BEFORE hello yes
(integer) 4
redis> LRANGE list2 0 -1
1) "yes"
2) "hello"
3) "world"
4) "hello"
7、LREM:移除元素
命令 | LREM list count element |
---|---|
效果 | 移除列表中指定元素element。count的值決定了移除元素的方式: 如果count為0,表示移除所有指定元素; 如果count為正整數,從列表左端開始移除count數量的指定元素; 如果count為負整數,從列表右端開始移除-count數量的指定元素。 |
返回值 | 返回被移除的元素的數量,也就是說如果不存在element或者列表不存在,返回0 |
redis> LPUSH list3 hello world hello foo hello
(integer) 5
redis> LREM list3 -2 hello
(integer) 2
redis> LRANGE list3 0 -1
1) "hello"
2) "foo"
3) "world"
8、LTRIM:修剪列表
命令 | LTRIM list start stop |
---|---|
效果 | 只保留給定範圍[start, stop]內的元素,移除其他元素。 |
返回值 | 返回OK。索引越界不會返回錯誤(例如,如果start超過了陣列的最大索引,將得到一個空列表,也就是說該列表鍵被移除。再如,如果start大於stop,得到的也是一個空列表。如果end超過了陣列的最大索引,將被視為-1) |
9、LLEN:獲取列表的長度
命令 | LLEN list |
---|---|
效果 | 獲取列表的長度 |
返回值 | 返回列表的長度。如果列表不存在,返回0 |
10、BLPOP、BRPOP、BRPOPLPUSH:阻塞式操作
BLPOP和BRPOP是帶有阻塞功能的彈出操作,它接受一個或多個列表以及一個秒級精度的超時時間作為引數。
命令 | BLPOP list1 [list2 ...] timeout |
---|---|
效果 | 從左往右依次檢查給定列表,一旦遇到非空列表就對其執行左端彈出,不會阻塞。如果所有列表都是空的,它將阻塞當前redis-cli客戶端並開始等待,直到有列表變為非空可以彈出元素,或者達到超時時間。如果timeout為0,將永遠阻塞直到可以彈出。 |
返回值 | 如果執行了彈出操作,返回一個二元列表,分別是執行了彈出操作的列表名、彈出的元素本身。如果超時,返回nil。 |
下面的例子中,list4為空而list5非空,客戶端不會阻塞,立即從list5左端彈出c。
redis> LPUSH list5 a b c
(integer) 3
redis> LPUSH list6 c d e
(integer) 3
redis> BLPOP list4 list5 list6 5
1) "list5"
2) "c"
redis> LRANGE list5 0 -1
1) "b"
2) "a"
下面的例子中,list7和list8都是空的,引發當前redis-cli客戶端阻塞,但是在等待的5秒鐘內另一個客戶端向list8中推入了元素a,因此當前客戶端成功彈出元素,並回到非阻塞狀態。注意展示的1.32s的阻塞時長是客戶端為了方便使用者新增的額外資訊,並非BLPOP的返回結果。
redis> BLPOP list7 list8 5 -- 阻塞
1) "list8" -- 彈出元素,解除阻塞
2) "a"
(1.32s)
下面的例子中,list7和list8都是空的,引發當前redis-cli客戶端阻塞,並且在等待的5秒鐘內一直沒有新元素新增至兩個列表,直到超時,並回到非阻塞狀態。
redis> BLPOP list7 list8 5 -- 阻塞
(nil) -- 超時,解除阻塞
(5.29s)
同樣,BRPOPLPUSH是RPOPLPUSH的阻塞版本。
命令 | BRPOPLPUSH source destination timeout |
---|---|
效果 | 如果源列表非空,行為和RPOPLPUSH一樣,彈出源列表最右端元素並推入目標列表左端,最後返回這個元素。如果源列表為空,阻塞客戶端直到源列表可以彈出元素,或者超時。如果timeout為0,將永遠阻塞直到可以彈出 |
返回值 | 如果在超時時間內彈出了元素,返回該元素。如果超時,返回nil |
11、總結
- LPUSH、LPUSHX、RPUSH、RPUSHX推入元素,它們都支援批量操作。
- LINSERT一次插入一個元素。
- LPOP、RPOP一次彈出一個元素,此外還有個較為綜合的RPOPLPUSH。
- LINDEX、LRANGE根據索引或索引範圍獲取元素,LSET根據索引設定元素。
- LREM移除一個或多個元素,LTRIM直接修剪列表。
- LLEN獲取列表長度。
- 有三個阻塞操作:BLPOP、BRPOP、BRPOPLPUSH。
四、集合(set)
Redis的集合鍵可以儲存任意多個各不相同的元素。
雖然列表也可以儲存多個元素,但集合和列表的區別在於:
- 列表可以儲存重複元素,集合只能儲存重複元素,即使新增已存在的元素也會被忽略;
- 列表的儲存是有序的,可以用索引獲取對應元素,集合是無序的,沒有索引的概念。
1、SADD、SREM:新增、移除元素
命令 | SADD set member1 [member2 ...] |
---|---|
效果 | 將一個或多個元素新增到集合中。會忽略已經存在的元素 |
返回值 | 返回成功新增的新元素數量 |
命令 | SREM set member1 [member2 ...] |
---|---|
效果 | 從集合中移除一個或多個元素。忽略不存在的元素 |
返回值 | 返回被移除的元素數量 |
redis> SADD set1 a b c
(integer) 3
redis> SADD set1 b d e
(integer) 2
redis> SREM set1 a d f
(integer) 2
2、SMOVE:將元素從一個集合移動到另一個集合
命令 | SMOVE source destination member |
---|---|
效果 | 將元素從源集合移動到目標集合 |
返回值 | 移動操作成功執行返回1。如果源集合不存在,或者source不在源集合中,返回0。(如果要移動的元素已經存在於目標集合,仍然會從源集合中移除,最終返回1) |
3、SCARD:獲取集合包含的元素數量
命令 | SCARD set |
---|---|
效果 | 獲取給定集合包含的元素數量 |
返回值 | 返回集合包含的元素數量 |
4、SISMEMBER:檢查給定元素是否存在於集合
命令 | SISMEMBER set member |
---|---|
效果 | 檢查給定元素是否存在於集合 |
返回值 | 存在返回1,不存在或集合本身不存在返回0 |
5、SMEMBERS:獲取集合包含的所有元素
命令 | SMEMBERS set |
---|---|
效果 | 獲取集合包含的所有元素 |
返回值 | 返回集合包含的所有元素。如果集合不存在,返回空集合 |
6、SRANDMEMBER、SPOP:隨機獲取元素
命令 | SRANDMEMBER set [count] |
---|---|
效果 | 從集合中隨機獲取指定數量的元素。如果不指定count,就只獲取一個元素。SRANDMEMBER不會將元素從集合中刪除。 |
返回值 | 如果沒有給定count,返回nil或單獨的元素。如果給定count,返回空列表或者列表,列表元素具體由count的值決定: 如果count大於集合長度,返回所有元素。 如果count為0,返回空集合。 如果count為負數,隨機返回-count個元素,並且這些元素中允許出現相同的值。(也就是說,如果-count大於集合長度,仍然會返回-count個元素,而不是所有元素) |
命令 | SPOP set [count] |
---|---|
效果 | 從集合中隨機移除指定數量的元素。如果不給定count,只移除一個元素。count不能為負數。 |
返回值 | 返回這些被移除的元素。如果count為0,不執行移除操作,返回空集合。 |
SPOP與SRANDMEMBER非常相似,主要區別在於SPOP會移除被隨機選中的元素,而SRANDMEMBER不會。
7、SINTER、SINTERSTORE、SUNION、SUNIONSTORE、SDIFF、SDIFFSTORE:多個集合的交集、並集、補集計算
SINTER和SINTERSTORE對一個或多個集合執行交集計算。set1和set2取交集,結果再和set3取交集,以此類推。特別地,如果只給定了一個集合,直接返回這個集合,此時相當於SMEMBERS。
命令 | SINTER set1 [set2 ...] |
---|---|
效果 | 對集合執行交集計算 |
返回值 | 返回交集結果的所有元素。 |
redis> SADD set2 a b c
(integer) 3
redis> SADD set3 c
(integer) 1
redis> SADD set4 c d e
(integer) 3
redis> SINTER set1 set2 set3
1) "c"
SINTERSTORE還能將計算結果儲存到指定鍵裡面:
命令 | SINTERSTORE destination set1 [set2 ...] |
---|---|
效果 | 對集合執行交集計算並把結果儲存到目的集合中。如果目的鍵已經存在,將會被覆蓋 |
返回值 | 返回結果集合的元素數量 |
SUNION和SUNIONSTORE對一個或多個集合執行並集計算。
命令 | SUNION set1 [set2 ...] |
---|---|
效果 | 對集合執行並集計算 |
返回值 | 返回並集結果的所有元素 |
命令 | SUNIONSTORE destination set1 [set2 ...] |
---|---|
效果 | 對集合執行交集計算並把結果儲存到目的集合中。如果目的鍵已經存在,將會被覆蓋 |
返回值 | 返回結果集合的元素數量 |
SDIFF和SDIFFSTORE對一個或多個集合執行並集計算。
命令 | SDIFF set1 [set2 ...] |
---|---|
效果 | 對集合執行差集計算:首先計算set1 - set2,然後對所得集合s執行s - set3,以此類推 |
返回值 | 返回差集結果的所有元素 |
命令 | SDIFFSTORE destination set1 [set2 ...] |
---|---|
效果 | 對集合執行差集計算並把結果儲存到目的集合中 |
返回值 | 返回結果集合的元素數量 |
8、總結
- SADD新增元素,SREM移除元素,支援操作多個元素。
- SMOVE在集合間移動一個元素。
- SISMEMBER檢查存在,SCARD獲取總數量,SMEMBERS獲取所有元素。
- SRANDMEMBER、SPOP都能隨機獲取一個或多個元素,後者還會移除元素。
- 集合之間支援交集、並集、差集運算。
五、有序集合(zset)
有序集合同時具有有序和集合兩種性質。在有序集合中,每個元素由一個成員和一個與成員關聯的分值組成,其中成員以字串方式儲存,分值以64位雙精度浮點數格式儲存。每個成員是獨一無二的,不會重複,並且每個成員按照自己的分值大小進行排序。如果分值相同,則按成員在字典序中的大小排序。分值不僅可以是數字,也可以是字串"+inf"或者"-inf",分別表示無窮大和無窮小。
1、ZADD:新增或更新成員
命令 | ZADD zset [NX|XX] [CH] [INCR] score1 member1 [score2 member2 ...] |
---|---|
效果 | 新增或更新成員。如果zset或member不存在,新增成員以及分值。如果member已經存在且與給定的不一致,更新分值。 XX和NX選項限制只進行新增或更新操作:如果給定了XX選項,則只更新已經存在於zset中的成員的分值,忽略不存在的;如果給定NX選項,只新增不存在於zset的成員和分值,忽略已經存在的成員。 CH選項決定了返回值是否統計更新分值的數量。(CH代表changed) INCR選項使得ZADD的行為類似於ZINCRBY,如果給定INCR選項,那麼只能傳入一對score和member,效果是對給定的成員的分值進行自增或自減操作 |
返回值 | 返回成功新增的新成員的數量(不含更新分值的)。如果給定CH選項,則返回被修改的成員的數量,既包括新新增的,也包括更新分值的。如果給定INCR選項,返回進行運算後的分值或者nil(使用了NX或XX選項且操作被忽略) |
redis> ZADD zset1 1 one 2 two
(integer) 2
redis> ZADD zset1 2 one 3 three 4 four
(integer) 2
redis> ZADD zset1 CH 2.5 one 3.5 four 5 five
(integer) 3
redis> ZADD zset1 NX 1 one
(integer) 0
redis> ZADD zset1 INCR -1.5 one
"1"
2、ZREM:移除指定成員
命令 | ZREM zset member1 [member2 ...] |
---|---|
效果 | 移除一個或多個成員以及相關聯的分值。如果給定的某個成員不存在,將被忽略。 |
返回值 | 返回移除的數量 |
3、ZSCORE:獲取成員的分值
命令 | ZSCORE zset member |
---|---|
效果 | 獲取成員的分值 |
返回值 | 返回成員的分值。如果zset不存在,或者member不存在,返回nil |
4、ZCARD:獲取有序集合的大小
命令 | ZCARD zset |
---|---|
效果 | 獲取有序集合包含的成員數量 |
返回值 | 返回zset包含的成員數量。如果集合不存在,返回0 |
5、ZINCRBY:對成員的分值執行增減操作
命令 | ZINCRBY zset increment member |
---|---|
效果 | 對成員的分值執行自增或自減操作並更新之。如果zset或者member不存在,相當於執行ZADD zset increment member。 |
返回值 | 返回運算後的分值 |
6、ZRANGE、ZREVRANGE:根據索引範圍獲取範圍內的成員
類似於列表的索引,ZRANGE和ZREVRANGE既可以接受正數索引,也可以接受負數索引。預設成員按照分值的大小升序排序,分值相同的成員再按字典序升序排列。
命令 | ZRANGE zset start end [WITHSCORES] |
---|---|
效果 | 以升序排列獲取指定索引範圍[start, end]內的成員 |
返回值 | 返回範圍內的成員。如果給定WITHSCORES選項,則按照member1,score1的形式同時返回成員和關聯分值。索引越界不會產生異常。 |
ZREVRANGE返回的是降序排名,此時成員按照分值的大小降序排序,並且分值相同的成員也會按字典序降序排列。
命令 | ZREVRANGE zset start end [WITHSCORES] |
---|---|
效果 | 以降序排列獲取指定索引範圍[start, end]內的成員 |
返回值 | 返回範圍內成員。如果給定WITHSCORES選項,則返回成員的同時也會返回關聯的分值。 |
redis> ZADD zset2 1 a 1 b 1 c 2 e
(integer) 4
redis> ZRANGE zset2 0 -1
1) "a"
2) "b"
3) "c"
4) "e"
redis> ZRANGE zset2 0 -1 WITHSCORES
1) "a"
2) "1"
3) "b"
4) "1"
5) "c"
6) "1"
7) "e"
8) "2"
redis> ZREVRANGE zset2 0 -1
1) "e"
2) "c"
3) "b"
4) "a"
7、ZREMRANGEBYRANK:根據索引範圍移除指定範圍內的成員
命令 | ZREMRANGEBYRANK zset start end |
---|---|
效果 | 從zset中移除指定索引範圍[start, end]內的成員 |
返回值 | 返回被移除成員的數量 |
8、ZRANK、ZREVRANK:根據成員獲取索引
ZRANK和ZRANGE正好相反,根據單個成員獲取索引。
命令 | ZRANK zset member |
---|---|
效果 | 獲取成員在zset中的升序排名(即索引),序號從0開始。 |
返回值 | 返回成員在zset中的索引。如果zset或member不存在,返回nil |
ZREVRANK類似於ZRANK,只不過返回的是降序排名。
命令 | ZREVRANK zset member |
---|---|
效果 | 獲取成員在zset中的降序排名,序號從0開始。 |
返回值 | 返回成員在zset中的降序排名。如果zset或member不存在,返回nil |
redis> ZREVRANGE zset2 0 -1
1) "e"
2) "c"
3) "b"
4) "a"
redis> ZREVRANK zset2 b
(integer) 2
9、ZRANGEBYSCORE、ZREVRANGEBYSCORE:根據分值獲取指定範圍內的成員
zset中每個成員和索引以及分值繫結,既能通過索引獲取成員,也能通過分值獲取成員。分值的範圍比較複雜:
- 和索引範圍一樣,分值範圍預設也是閉區間;
- 如果想使用開區間,在分值引數的前面加一個小括號(。例如ZRANGEBYSCORE zset (1 5表示1 < score <= 5,再如ZRANGEBYSCORE zset (5 (10表示5 < score < 10;
- 還可以使用-inf和+inf表示無窮小和無窮大,用於只需要分值範圍的上限和下限時。
命令 | ZRANGEBYSCORE zset min max [WITHSCORES] [LIMIT offset count] |
---|---|
效果 | 以升序排列獲取zset中分值介於min和max內的成員。使用LIMIT選項可以從結果中只取一部分,例如LIMIT 1 3表示取第2-4個結果。 |
返回值 | 返回範圍內成員。如果給定WITHSCORES選項,則返回成員的同時也會返回關聯的分值。 |
ZREVRANGEBYSCORE正好相反。需要注意的是,先接受max引數再接受min引數。
命令 | ZREVRANGEBYSCORE zset max maminx [WITHSCORES] [LIMIT offset count] |
---|---|
效果 | 以升序排列獲取zset中分值介於min和max內的成員。使用LIMIT選項可以從結果中只取一部分,例如LIMIT 1 3表示取第2-4個結果。 |
返回值 | 返回範圍內成員。如果給定WITHSCORES選項,則返回成員的同時也會返回關聯的分值。 |
redis> ZADD zset3 1.3 one 2.4 two 4.1 four 6.2 six 2.4 two2
(integer) 5
redis> ZRANGEBYSCORE zset3 -inf +inf
1) "one"
2) "two"
3) "two2"
4) "four"
5) "six"
redis> ZREVRANGEBYSCORE zset3 +inf -inf
1) "six"
2) "four"
3) "two2"
4) "two"
5) "one"
redis> ZRANGEBYSCORE zset3 1 6 LIMIT 1 2 -- 取升序的第二和第三個
1) "two"
2) "two2"
10、ZREMRANGEBYSCORE:根據分值移除指定範圍內的成員
命令 | ZREMRANGEBYSCORE zset min max |
---|---|
效果 | 從升序排列的zset中移除指定分值範圍min和max內的成員。分值範圍參考ZRANGEBYSCORE |
返回值 | 返回被移除成員的數量 |
11、ZCOUNT:統計指定分值範圍內的成員數量
命令 | ZCOUNT zset min max |
---|---|
效果 | 統計指定分值範圍內的成員數量。分值範圍參考ZRANGEBYSCORE |
返回值 | 返回指定分值範圍內的成員數量 |
12、ZRANGEBYLEX、ZREVRANGEBYLEX:根據字典序獲取指定範圍內的成員
如果有序集合中所有成員的分值都相同,它相當於一個按字典序自動排列的列表,此時ZRANGEBYSCORE這樣的命令已經沒有意義。Redis提供了諸如ZRANGEBYLEX這樣的命令,根據字典序進行排序、刪除、計數等操作。特別地,它沒有WITHSCORES選項。
字典序的範圍必須是以下四種之一:
- 以小括號(開頭的值,表示開區間;
- 以中括號[開頭的值,表示閉區間;
- 減號-,表示無窮小;
- 加號+,表示無窮大。
注意:如果有序集合中的成員分值不同,返回值將變得不可預測。
命令 | ZRANGEBYLEX zset min max [LIMIT offset count] |
---|---|
效果 | 以字典序獲取介於min和max內的成員。使用LIMIT選項可以從結果中只取一部分 |
返回值 | 返回範圍內成員 |
和ZREVRANGEBYSCORE一樣,ZREVRANGEBYLEX也是先接受max引數再接受min引數。
命令 | ZREVRANGEBYLEX zset max min [LIMIT offset count] |
---|---|
效果 | 以逆字典序獲取介於min和max內的成員。使用LIMIT選項可以從結果中只取一部分 |
返回值 | 返回範圍內成員 |
redis> ZADD zset4 0 a 0 b 0 c 0 d 0 e 0 f 0 g
(integer) 7
redis> ZREVRANGEBYLEX zset4 [c -
1) "c"
2) "b"
3) "a"
redis> ZRANGEBYLEX zset4 (f +
1) "g"
redis> ZRANGEBYLEX zset4 [aaa (d
1) "b"
2) "c"
13、ZREMRANGEBYLEX:根據字典序移除指定範圍內的成員
命令 | ZREMRANGEBYLEX zset min max |
---|---|
效果 | 移除指定字典序範圍min和max內的成員。字典序範圍參考ZRANGEBYLEX |
返回值 | 返回被移除成員的數量 |
14、ZLEXCOUNT:根據字典序統計位於指定範圍內的成員數量
命令 | ZCOUNT zset min max |
---|---|
效果 | 統計位於字典序指定範圍內的成員數量。字典序範圍參考ZRANGEBYLEX |
返回值 | 返回位於字典序指定範圍內的成員數量 |
15、ZUNIONSTORE、ZINTERSTORE:並集和交集運算
命令 | ZUNIONSTORE destination numzsets zset1 [zset2 ...] [WEIGHTS weight1 [weight2 ...]] [AGGREGATE SUM|MIN|MAX] |
---|---|
效果 | 進行並集運算並存儲到目標有序集合中,如果destination鍵已經存在,將會被覆蓋。 取並集的成員的分值由原來的多個有序集合的成員的分值相加得到。如果給定了AGGREGATE選項,可以改變分值的計算方式:SUM(預設)、MIN、MAX。 numzsets指定參與計算的有序集合數量,必須和zset的數量一致否則報錯。 如果使用WEIGHTS選項,需要為每個給定的有序集合分別設定一個權重,新分值由成員的分值與權重之積再聚合計算得到。可以使用集合作為並集運算的輸入,集合的分值視為1 |
返回值 | 返回計算結果包含的成員數量 |
下面的例子,分別用兩種聚合方式求出了並集
redis> ZADD zset5 1 a 2 b 3 c
(integer) 3
redis> ZADD zset6 2 a 5 c 8 d
(integer) 3
redis> ZUNIONSTORE store1 2 zset5 zset6 WEIGHTS 3 2
(integer) 4
redis> ZRANGE store1 0 -1
1) "b"
2) "a"
3) "d"
4) "c"
redis> ZRANGE store1 0 -1 WITHSCORES
1) "b"
2) "6" -- 6 = 2 * 3
3) "a"
4) "7" -- 7 = 1 * 3 + 2 * 2
5) "d"
6) "16"
7) "c"
8) "19"
redis> ZUNIONSTORE store2 2 zset5 zset6 WEIGHTS 3 2 AGGREGATE MIN
(integer) 4
redis> ZRANGE store2 0 -1 WITHSCORES
1) "a"
2) "3" -- 3 = min(1 * 3, 2 * 2)
3) "b"
4) "6"
5) "c"
6) "9"
7) "d"
8) "16"
下面的例子,將一個有序集合和一個集合取並集,集合中成員的分值視為1。
redis> SMEMBERS set1
1) "b"
2) "e"
3) "c"
redis> ZRANGE zset5 0 -1 WITHSCORES
1) "a"
2) "1"
3) "b"
4) "2"
5) "c"
6) "3"
redis> ZUNIONSTORE store3 2 zset5 set1
(integer) 4
redis> ZRANGE store3 0 -1 WITHSCORES
1) "a"
2) "1"
3) "e"
4) "1"
5) "b"
6) "3"
7) "c"
8) "4"
ZINTERSTORE對有序集合取交集計算。
命令 | ZINTERSTORE destination numzsets zset1 [zset2 ...] [WEIGHTS weight1 [weight2 ...]] [AGGREGATE SUM|MIN|MAX] |
---|---|
效果 | 進行交集運算並存儲到目標有序集合中,其他類似ZUNIONSTORE |
返回值 | 返回計算結果包含的成員數量 |
16、ZPOPMAX、ZPOPMIN:彈出分值最高和最低的成員
命令 | ZPOPMAX zset [count] |
---|---|
效果 | 彈出count個分值最高的成員,不給定count則彈出1個 |
返回值 | 返回被彈出的這些成員和對應分值 |
命令 | ZPOPMIN zset [count] |
---|---|
效果 | 彈出count個分值最低的成員,不給定count則彈出1個 |
返回值 | 返回被彈出的這些成員和對應分值 |
17、BZPOPMAX、BZPOPMIN:阻塞式彈出分值最高和最低的成員
命令 | BZPOPMAX zset1 [zset2 ...] timeout |
---|---|
效果 | 依次檢查給定的所有zset並對第一個非空zset彈出其內最大分值的元素。如果所有zset都沒有可彈出的元素,就阻塞客戶端直到可以彈出或超時。如果timeout設定為0,表示一直阻塞,直到可彈出元素出現為止。 |
返回值 | 成功彈出元素後返回一個三元列表:被彈出元素所在zset名、被彈出元素的成員、被彈出成員的分值。如果超時,返回nil。 |
命令 | BZPOPMIN zset1 [zset2 ...] timeout |
---|---|
效果 | 類似於BZPOPMAX,只是彈出的是分值最低的成員 |
返回值 | 同BZPOPMAX |
redis> ZRANGE zset5 0 -1 WITHSCORES
1) "a"
2) "1"
3) "b"
4) "2"
5) "c"
6) "3"
redis> BZPOPMIN zset5 4
1) "zset5"
2) "a"
3) "1"
18、總結
- ZADD新增一個或多個成員-分值對,ZREM移除一個或多個成員。ZADD還能當ZINCRBY用。
- 用單個成員能做什麼?獲取分值、更新分值、獲取索引,ZSCORE、ZINCRBY、ZRANK、ZREVRANK。
- 用索引能做什麼?獲取和移除,ZRANGE、ZREVRANGE、ZREMRANGEBYRANK。
- 分值可以使用開區間、-inf和+inf。用分值能做什麼?獲取、移除、計數,ZRANGEBYSCORE、ZREVRANGEBYSCORE、ZREMRANGEBYSCORE、ZCOUNT。
- 獲取集合大小:ZCARD。
- 字典序相關:ZRANGEBYLEX、ZREVRANGEBYLEX、ZREMRANGEBYLEX、ZLEXCOUNT,僅用於分值都相同。
- 並集和交集運算:ZUNIONSTORE、ZINTERSTORE。
- 阻塞或非阻塞彈出分值最高最低成員:ZPOPMAX、ZPOPMIN、BZPOPMAX、BZPOPMIN。
六、HyperLogLog
以下引用自Redis中文網:
Redis HyperLogLog是用來做基數統計的演算法,HyperLogLog的優點是,在輸入元素的數量或者體積非常非常大時,計算基數所需的空間總是固定的、並且是很小的。
在 Redis 裡面,每個HyperLogLog鍵只需要花費12 KB記憶體,就可以計算接近2^64個不同元素的基數。這和計算基數時,元素越多耗費記憶體就越多的集合形成鮮明對比。
但是,因為HyperLogLog只會根據輸入元素來計算基數,而不會儲存輸入元素本身,所以HyperLogLog不能像集合那樣,返回輸入的各個元素。
什麼是基數?
比如資料集 {1, 3, 5, 7, 5, 7, 8},那麼這個資料集的基數集為 {1, 3, 5 ,7, 8},基數(不重複元素)為5。基數估計就是在誤差可接受的範圍內,快速計算基數。
1、PFADD:新增指定元素到HyperLogLog中
命令 | PFADD hyperloglog element1 [element2 ...] |
---|---|
效果 | 將元素新增到HyperLogLog集合中 |
返回值 | 如果給定元素中出現了至少一個新元素,返回1,表示因為新元素的新增使得計算出的近似基數發生變化。如果沒有新元素,返回0,表示計算出的近似基數不變 |
redis> PFADD hll1 a b c d e f g
(integer) 1
redis> PFCOUNT hll1
(integer) 7
2、PFCOUNT:返回集合的近似基數
命令 | PFCOUNT hyperloglog1 [hyperloglog2 ...] |
---|---|
效果 | 獲取集合的近似基數。如果傳入多個HyperLogLog,先進行並集計算再求並集集合的近似基數 |
返回值 | 返回集合的近似基數 |
redis> PFADD hll2 hello world yes
(integer) 1
redis> PFADD hll2 yes yes yes
(integer) 0
redis> PFADD hll3 a b c d
(integer) 1
redis> PFCOUNT hll2 hll3
(integer) 7
3、PFMERGE:計算並存儲多個HyperLogLog的並集
命令 | PFMERGE destination hyperloglog1 [hyperloglog2 ...] |
---|---|
效果 | 對多個給定的hyperloglog執行並集計算,把並集結果儲存到destination中 |
返回值 | 返回OK |
PFCOUNT在計算多個HyperLogLog的並集後會將其儲存到一個臨時的HyperLogLog中再得到近似基數,最後將臨時的HyperLogLog刪除掉。而PFMERGE會儲存起來。
七、點陣圖(bitmap)
Redis的點陣圖是由多個二進位制位組成的陣列,每個二進位制位有自己的偏移量(索引),通過偏移量即可對指定的二進位制位進行操作。
點陣圖是在字串的基礎上實現的,故點陣圖鍵會被視為一個字串鍵,GET、SET、STRLEN、GETRANGE等同樣適用。
1、SETBIT:設定二進位制位的值
命令 | SETBIT bitmap offset value |
---|---|
效果 | 為點陣圖指定偏移量上的二進位制位設定值,值只能為1或0。如果點陣圖當前的長度小於offset,將對該點陣圖進行擴充套件,並且將所有未被設定的二進位制位初始化為0。offset不能為負數。 |
返回值 | 返回被設定之前的舊值。如果bitmap不存在或offset大於當前點陣圖大小,返回0 |
2、GETBIT:獲取二進位制位的值
命令 | GETBIT bitmap offset |
---|---|
效果 | 獲取點陣圖指定偏移量上的二進位制位的值。offset不能為負數 |
返回值 | 返回指定偏移量上的二進位制位的值。如果bitmap不存在或offset大於當前點陣圖大小,返回0 |
3、BITCOUNT:統計被設定的二進位制位數量
命令 | BITCOUNT bitmap [start end] |
---|---|
效果 | 統計點陣圖中值為1的二進位制位數量。如果給定了start和end,表示對指定位元組範圍[start, end]內的二進位制位進行統計。start和end可以是負數。 |
返回值 | 返回值為1的二進位制位數量 |
注意:BITCOUNT中的start和end與GETRANGE中的start和end一樣,都是位元組偏移量,而不是二進位制偏移量。例如BITCOUNT bitmap 0 2統計的是前三個位元組中包含的所有二進位制位,而不是前三個二進位制位。此外,這裡的位元組偏移量是可以使用負數索引的。
下面的例子,由於l和d對應的二進位制是0110 1100和0110 0100,所以BITCOUT統計的結果是7。之後將l最高位的1改為0(偏移量為9*8+1=73),0010 1100對應符號為英文逗號(,)。
redis> SET bitmap1 'hello world'
OK
redis> STRLEN bitmap1
(integer) 11
redis> BITCOUNT bitmap1 -2 -1
(integer) 7
redis> SETBIT bitmap1 73 0
(integer) 1
redis> BITCOUNT bitmap1 -2 -1
(integer) 6
redis> GETRANGE bitmap1 0 -1
"Hello wor,d"
4、BITPOS:查詢第一個指定的二進位制位值
命令 | BITPOS bitmap value [start] [end] |
---|---|
效果 | 查詢第一個被設定為指定值的二進位制位。如果給定start和end,則只在位元組範圍[start, end]內的二進位制位中查詢。 |
返回值 | 返回該二進位制位的偏移量。如果只給定了start沒有給定end,則end視為-1。 如果查詢的是1,但點陣圖不存在或所有範圍內的位都是0,返回-1。 如果查詢的是0且沒有給定start和end,且點陣圖中所有位都為1,返回點陣圖最大偏移量+1。 特別地,在同時給定了start和end的情況下,如果範圍在bitmap的長度之外,返回-1;如果在範圍內均沒有查詢的值,也返回-1 |
下面這個例子展示了多種情況下查詢失敗的返回值
redis> SET bitmap1 "\x00"
OK
redis> STRLEN bitmap1
(integer) 1
redis> BITPOS bitmap1 1
(integer) -1
redis> BITPOS bitmap1 1 0
(integer) -1
redis> SET bitmap1 "\xff"
OK
redis> BITPOS bitmap1 0
(integer) 8
redis> BITPOS bitmap1 0 0
(integer) 8
redis> BITPOS bitmap1 0 0 0
(integer) -1
5、BITOP:執行二進位制運算
命令 | BITOP operation destination bitmap1 [bitmap2 ...] |
---|---|
效果 | 執行二進位制位運算並存儲到結果中。operation必須是是AND、OR、XOR、NOT之一,分別對應與、或、異或、非,其中AND、OR、XOR允許輸入任意多個bitmap,而NOT只允許輸入一個。如果點陣圖長度不同,較短的點陣圖補0 |
返回值 | 返回被儲存點陣圖的位元組長度 |
redis> SET bitmap1 "\x6c"
OK
redis> SET bitmap2 "\xa7z"
OK
redis> BITOP AND bitmap3 bitmap1 bitmap2
(integer) 2
redis> GETRANGE bitmap3 0 -1
"$\x00"
redis> BITOP XOR bitmap3 bitmap1 bitmap2
(integer) 2
redis> GETRANGE bitmap3 0 -1
"\xcbz"
redis> BITOP NOT bitmap3 bitmap1
(integer) 1
redis> GETRANGE bitmap3 0 -1
"\x93"
6、BITFIELD:在點陣圖中儲存整數值
BITFIELD命令可以在點陣圖的任意區域中儲存整數值,並對這些整數值執行加法或減法操作。它支援SET、GET、INCRBY、OVERFLOW這四個子命令,以下分別介紹。
SET子命令給區域設定值:
BITFIELD bitmap SET type offset|#index value
- type指定被設定值的型別,必須以i或u開頭,後跟要設定的值的位長度,i表示有符號整數,u為無符號整數。如i8為有符號8位整數,u16為無符號16位整數。
- offset表示設定位置的位偏移量,也可以用#index,表示根據給定型別的位長度的索引。如u8 #132表示該點陣圖的第133個8位無符號整數,等同於u8 1056。
- value指定被設定的整數值。如果超過了type指定的型別,會被截斷。例如,有符號4位整數的最大值為15,這意味著u4 0 123相當於u4 0 11。
返回指定區域被設定前的舊值。
BITFIELD命令允許一次執行多個子命令,比如一次使用多個SET設定多個區域。返回陣列,對應每一個子命令的返回結果。
redis> BITFIELD bitmap4 SET u4 0 123
1) (integer) 0
redis> GET bitmap4
"\xb0"
redis> BITFIELD bitmap4 SET u4 0 13 SET u4 4 14 -- 一次設定兩個
1) (integer) 11
2) (integer) 0
redis> GET bitmap4
"\xde"
redis> BITFIELD bitmap4 SET u3 9 7 SET u4 #4 10 -- #4即給位偏移量的16-19進行設定
1) (integer) 0
2) (integer) 0
redis> GET bitmap4
"\xdep\xa0" -- p的二進位制為0111 0000
GET子命令獲取區域儲存的值:
BITFIELD bitmap GET type offset|#index
這些引數的意義與SET子命令中同名引數的意義完全一樣。
如果點陣圖不存在,或者超過了邊界,返回0。
redis> GET bitmap4
"\xdep\xa0"
redis> BITFIELD bitmap4 GET u8 #0 GET u8 #1 GET u8 #2 GET u8 #3
1) (integer) 222 -- \xde對應十進位制是222
2) (integer) 112 -- p的ascii編號是112
3) (integer) 160 -- \xa0對應十進位制是160
4) (integer) 0 -- 越界
redis> BITFIELD bitmap4 GET u16 #0 GET u16 #1
1) (integer) 56944 -- \xde\x70
2) (integer) 40960 -- \xa0\x00,後補0
INCRBY子命令執行加法或減法操作:
BITFIELD bitmap INCRBY type offset|#index increment
返回整數的當前值。
redis> GET bitmap4
"\xdep\xa0"
redis> BITFIELD bitmap4 INCRBY u8 0 1 INCRBY u8 #1 -2
1) (integer) 223
2) (integer) 110
redis> GET bitmap4
"\xdfn\xa0"
OVERFLOW用於控制INCRBY子命令發生計算溢位時的行為:
BITFIELD bitmap OVERFLOW WRAP|SAT|FAIL
- WRAP(預設),向上溢位的整數值從型別的最小值開始計算,向下溢位的整數值從型別的最大值開始計算;
- SAT,飽和運算(saturation arithmetic),如果發生向上溢位,得到的結果是型別的最大值,如果發生向下溢位,得到的結果是型別的最小值;
- FAIL,檢測到計算會引發溢位則拒絕計算,返回nil表示計算失敗。
OVERFLOW命令只會對排在它後面的那些INCRBY產生效果。
redis> GET bitmap4
"\xdfn\xa0"
redis> BITFIELD bitmap4 INCRBY u4 0 3 OVERFLOW SAT INCRBY u4 #1 3
1) (integer) 2
2) (integer) 15
redis> GET bitmap4
"/n\xa0" -- /對應0x2F
如果用字串或雜湊儲存整數,Redis會先給整數分配一個long型別的值,並使用物件去包裹這個值,再把物件關聯到資料庫或雜湊中。而BITFIELD允許使用者自行指定要儲存的整數的型別,且不會用物件包裹這些整數,一定程度上減少了帶來的記憶體消耗。
7、總結
- 用位偏移量設定和獲取位的值:SETBIT、GETBIT。
- BITCOUNT、BITPOS接受的是位元組索引範圍,而不是位索引範圍。
- BITFIELD執行位運算。
- BITFIELD在點陣圖中儲存整數值。
八、地理座標GEO
Redis GEO是Redis在3.2版本新新增的特性,使用者可以將經緯度格式的地理座標儲存到Reids中,並對這些座標執行距離計算、範圍查詢等操作。但是極地附近的地理座標將被限制,不能被儲存。總地來說,經緯度的範圍如下:
- 精度的範圍為-180到180;
- 緯度的範圍為 -85.05112878到85.05112878。
Redis使用zset儲存GEO資料,每儲存一個位置名稱以及經緯度時,Redis會通過Geohash演算法把經緯度轉換為一個獨一無二的52位整數,作為分值儲存到zset中。(根據Geohash也可以還原出經度和緯度。)因此zset的命令,如ZRANGE、ZCARD、ZREM等也可以使用。
1、GEOADD:新增座標
命令 | GEOADD geo longitude1 latitude1 member1 [longitude2 latitude2 member2 ...] |
---|---|
效果 | 將給定的一個或多個經緯度座標儲存到位置集合中並設定相應的名字。如果位置已經存在,則更新座標。 |
返回值 | 返回新增到位置集合的座標數量(不包含更新的) |
redis> GEOADD geo1 114.05 22.55 shenzhen 113.27 23.13 guangzhou 113.12 23.02 foshan
(integer) 3
2、GEOPOS:根據位置名獲取座標
命令 | GEOPOS geo member1 [member2 ...] |
---|---|
效果 | 獲取給定位置的座標 |
返回值 | 返回一個數組,分別記錄每個位置的經度和緯度 |
redis> GEOPOS geo1 shenzhen guangzhou foshan dongguan
1) 1) "114.04999762773513794"
2) "22.5500010475923105"
2) 1) "113.27000051736831665"
2) "23.13000101271457254"
3) 1) "113.12000066041946411"
2) "23.01999918384158406"
4) (nil)
3、GEODIST:計算兩個位置之間的直線距離
命令 | GEODIST geo member1 member2 [unit] |
---|---|
效果 | 計算兩個位置之間的直線距離。unit指定要使用的單位,預設為米,可選:m、km、mi(英里)、ft(英尺) |
返回值 | 返回直線距離。如果至少有一個成員不存在,返回nil |
redis> GEODIST geo1 shenzhen guangzhou km
"102.7337"
redis> GEODIST geo1 shenzhen foshan
"108755.5425"
redis> GEODIST geo1 shenzhen dongguan ft
(nil)
4、GEORADIUS:查詢指定半徑範圍內的其他位置
命令 | GEORADIUS geo longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE geo] [STOREDIST zset] |
---|---|
效果 | 指定一個經緯度為中心點,從位置集合中找出位於中心點指定半徑範圍內的其他位置。 如果給定WITHCOORD選項,每返回一個位置還會返回該位置的座標。 如果給定WITHDIST選項,每返回一個位置還會返回該位置與中心點之間的距離,單位與給定的unit一致。 如果給定WITHHASH選項,每返回一個位置還會返回該位置的geohash,注意返回的是一個整數,與GEOHASH返回的字串不一樣,但這兩個值底層的二進位制位相同。 如果給定COUNT選項,限制返回的位置數量,必須為正整數。 如果給定ASC選項,將根據中心點到位置的距離由近到遠返回這些位置;DESC反之,由遠到近。 如果給定STORE選項,會將結果(位置名+經緯度)儲存起來。 如果給定STOREDIST選項,會將結果(位置名+距離)儲存到有序集合鍵中。 |
返回值 | 返回這些位置。如果給定了STORE或STOREDIST選項,則返回儲存的成員數量。 |
redis> GEORADIUS geo1 113 22 125 km
1) "shenzhen"
2) "foshan"
redis> GEORADIUS geo1 113 22 125 km WITHCOORD
1) 1) "shenzhen"
2) 1) "114.04999762773513794"
2) "22.5500010475923105"
2) 1) "foshan"
2) 1) "113.12000066041946411"
2) "23.01999918384158406"
redis> GEORADIUS geo1 113 22 125 km WITHDIST WITHCOORD ASC
1) 1) "foshan"
2) "114.1188"
3) 1) "113.12000066041946411"
2) "23.01999918384158406"
2) 1) "shenzhen"
2) "124.1843"
3) 1) "114.04999762773513794"
2) "22.5500010475923105"
5、GEORADIUSBYMEMBER:查詢指定位置半徑範圍內的其他位置
命令 | GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE geo] [STOREDIST zset] |
---|---|
效果 | 和GEORADIUS作用一樣,不過GEORADIUSBYMEMBER是通過選擇位置集合中的一個位置來作為中心點。注意會把作為中心點的自己也返回。 |
返回值 | 返回這些位置(包括自己)。如果給定了STORE或STOREDIST選項,則返回儲存的成員數量。 |
6、GEOHASH:獲取指定位置的Geohash值
命令 | GEOHASH geo member1 [member2 ...] |
---|---|
效果 | 獲取指定位置的Geohash字串。 |
返回值 | 返回一個長度為11的字串,相比內部儲存的52位整數在資訊上略有丟失,但無傷大雅。注意通過GEOHASH獲得的字串和通過GEORADIUS、GEORADIUSBYMEMBER的WITHHASH選項返回的不一樣,後者即為有序集合記憶體儲的整數 |
redis> GEOHASH geo1 shenzhen guangzhou
1) "ws10730em80"
2) "ws0e9d8wn20"
九、資料庫操作
所有的鍵,無論是字串鍵、雜湊鍵、列表鍵等,都會被儲存到資料庫這個容器中。Redis預設在啟動時建立16個數據庫,這些資料庫使用從0開始的整數號碼作為標識,一直到15號。當我們啟動redis-cli客戶端時,預設進入0號資料庫。
雖然在同一個資料庫中不允許鍵同名,但在不同的資料庫中可以存在相同的鍵。
1、SELECT:切換資料庫
命令 | SELECT index |
---|---|
效果 | 切換至指定的資料庫 |
返回值 | 返回OK |
2、KEYS:獲取所有與給定匹配符相匹配的鍵
命令 | KEYS pattern |
---|---|
效果 | 獲取所有與給定匹配符相匹配的鍵。 |
返回值 | 返回所有與給定匹配符相匹配的鍵 |
可使用的匹配符:
匹配符 | 作用 | 示例 |
---|---|---|
* | 匹配0個或任意多個任意字元 | h*llo匹配hllo、heeeello |
? | 匹配任意的單個字元 | h?llo匹配hello、hallo、hxllo |
[] | 匹配括號中的單個字元 | h[ae]llo匹配hello、hallo但是不匹配hillo |
[?-?] | 匹配範圍中的單個字元 | h[a-b]llo匹配hallo、hbllo |
redis> KEYS * -- 獲取資料庫中所有鍵
3、SCAN、HSCAN、SSCAN、ZSCAN:以漸進方式迭代
SCAN、HSCAN、SSCAN、ZSCAN都能對資料的集合進行迭代:
- SCAN迭代當前資料庫中所有鍵;
- HSCAN迭代指定雜湊中所有欄位和值;
- SSCAN迭代指定集合中所有元素;
- ZSCAN迭代指定有序集合中所有成員和關聯分值。
這些迭代都是漸進式的,一次只返回少量資料,而不會像KEYS或者SMEMBERS一次返回所有內容,避免了資料較多時阻塞伺服器的情況。
迭代需要用到遊標。在一次完整的迭代中,第一次迭代時遊標為0。之後每次獲得一部分資料的同時,Redis會返回一個新遊標,通過重複使用遊標來迭代剩餘的資料。一旦返回的遊標為0,就表示本次迭代已經完成。
對於一次完整的迭代,SCAN等命令有如下特點:
- 在迭代開始前就存在,並且迭代結束後仍然存在的資料一定會被返回,反之在迭代開始前就被移除,並且迭代結束後也沒有添加回來的資料一定不會被返回;
- 在迭代開始後才新增的資料,是否被返回是不確定的;
- 同一個資料有可能被返回多次,因此使用者需要自己檢測和過濾;
- 每次返回的數量是不確定的,甚至可能一個都不返回,但是隻要返回的遊標不為0,迭代就沒有結束;
- 迭代的過程中可以隨時停止迭代,而不需要向伺服器報告,也可以隨時開始一個新的完整迭代。
命令 | SCAN cursor [MATCH pattern] [COUNT count] |
---|---|
效果 | 迭代當前資料庫中所有鍵。cursor是每次迭代時使用的遊標,第一次迭代為0。 MATCH選項指定匹配符,不使用MATCH選項相當於KEYS * 的迭代版本。 COUNT選項提供下一次迭代期望返回的數量,但僅僅是期望值,下次迭代返回的鍵數量仍然是不確定的,當然更大的COUNT有助於獲得更多鍵。不給定COUNT,預設為10。在完整迭代中每次可以使用不一樣的COUNT。 |
返回值 | 返回下一次迭代的遊標以及本次迭代得到的所有鍵 |
redis> SCAN 0 MATCH *set*
1) "36"
2) 1) "zset4"
2) "set4"
redis> SCAN 36 MATCH *set*
1) "42"
2) 1) "zset2"
HSCAN迭代指定雜湊中所有欄位和值:
HSCAN hash cursor [MATCH pattern] [COUNT count]
redis> HSET hash2 a 1 b 2 c 3 d 4 e 5
(integer) 5
redis> HSCAN hash2 0
1) "0"
2) 1) "a"
2) "1"
3) "b"
4) "2"
5) "c"
6) "3"
7) "d"
8) "4"
9) "e"
10) "5"
SSCAN迭代指定集合中所有元素:
SSCAN set cursor [MATCH pattern] [COUNT count]
redis> SSCAN set1 0
1) "0"
2) 1) "b"
2) "e"
3) "c"
ZSCAN迭代指定有序集合中所有成員和關聯分值:
ZSCAN zset cursor [MATCH pattern] [COUNT count]
redis> ZSCAN zset5 0
1) "0"
2) 1) "b"
2) "2"
3) "c"
4) "3"
4、RANDOMKEY:隨機返回一個鍵
命令 | RANDOMKEY |
---|---|
效果 | 隨機返回一個鍵,不會移除返回的鍵 |
返回值 | 返回一個鍵。如果資料庫為空,返回nil |
5、EXISTS:檢查鍵是否存在
命令 | EXISTS key1 [key2 ...] |
---|---|
效果 | 檢查給定鍵是否存在 |
返回值 | 返回存在的鍵的數量 |
6、DEL:移除鍵
命令 | DEL key1 [key2 ...] |
---|---|
效果 | 移除指定的鍵 |
返回值 | 返回成功移除的數量 |
7、UNLINK:非同步方式移除指定的鍵
命令 | UNLINK key1 [key2 ...] |
---|---|
效果 | DEL是同步移除的,如果待移除的鍵非常大或多,伺服器在執行過程中可能會被阻塞。UNLINK是非同步的,在呼叫時只會在資料庫中移除對該鍵的引用,實際移除操作交給後臺執行緒執行,不會造成伺服器阻塞。 |
返回值 | 返回被移除鍵的數量 |
8、TYPE:檢視鍵的型別
命令 | TYPE key |
---|---|
效果 | 檢視鍵的型別 |
返回值 | 返回值可能是:string(包括Hyperloglog和點陣圖)、hash、list、set、zset(包括地理位置)、stream。如果鍵不存在,返回none |
9、RENAME、RENAMENX:修改鍵名
命令 | RENAME key newkey |
---|---|
效果 | 修改鍵名。如果key不存在,報錯。如果newkey已存在,會先移除newkey,再執行改名操作 |
返回值 | 返回OK。如果key不存在,返回異常。即使key和newkey相同也不會返回異常 |
命令 | RENAMENX key newkey |
---|---|
效果 | 僅當新鍵名尚未被佔用的情況下改名。 |
返回值 | 修改成功返回1,否則返回0。如果key不存在,返回異常 |
10、SORT:對鍵的值進行排序
SORT key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern] ...] [ASC|DESC] [ALPHA] [STORE destination]
對列表元素、集合元素和有序集合的成員進行排序。
- 使用ASC或DESC選項指定排序方式為升序或降序,不指定預設為升序ASC
- 使用LIMIT選項返回部分結果,預設情況下它等同於LIMIT 0 10
- 預設只進行數字排序,如果值包含非數字,將會返回錯誤,如果想執行字串排序操作,使用ALPHA選項
- 使用destination選項將排序結果儲存為列表,最後返回的是被儲存的元素數量
預設情況下,排序權重就是成員本身,即使是有序集合也是如此(而不是關聯分值)。
redis> SMEMBERS set1
1) "b"
2) "e"
3) "c"
redis> SORT set1 ALPHA DESC
1) "e"
2) "c"
3) "b"
redis> LRANGE list2 0 -1
1) "yes"
2) "hello"
3) "world"
4) "hello"
redis> SORT list2 ALPHA
1) "hello"
2) "hello"
3) "world"
4) "yes"
redis> ZRANGE zset3 0 -1
1) "one"
2) "two"
3) "two2"
4) "four"
5) "six"
redis> SORT zset3 ALPHA
1) "four"
2) "one"
3) "six"
4) "two"
5) "two2"
預設情況下返回被排序的元素作為結果,如果使用GET選項可以獲取其他值作為結果:
SORT key [GET pattern [GET pattern] ...]
pattern可以是:
1、包含*的字串,表示被排序的元素與*進行替換,構建出一個鍵名,再獲取該鍵的值作為返回值。
下面這個例子,SORT的執行過程如下:
①首先對fruit集合的各個元素進行排序;
②將排序後的元素逐個與*-price替換,得到apple-price等鍵名;
③最後取得這些鍵名對應值,作為返回結果。
redis> MSET apple-price 8 banana-price 5 mango-price 6
OK
redis> SADD fruits apple banana mango pear
(integer) 4
redis> SORT fruits ALPHA GET *-price
1) "8"
2) "5"
3) "6"
4) (nil)
2、包含*和->的字串,->前的字串被視為雜湊名,->後面的字串被視為欄位名,被排序的元素與*進行替換,構建雜湊鍵名,再獲取欄位的值作為返回值。
redis> HSET apple price 8
(integer) 1
redis> HSET banana price 5
(integer) 1
redis> HSET mango price 6
(integer) 1
redis> SORT fruits ALPHA GET *->price
1) "8"
2) "5"
3) "6"
4) (nil)
3、單獨的#,返回這個元素本身
redis> SORT fruits ALPHA GET # GET *->price
1) "apple"
2) "8"
3) "banana"
4) "5"
5) "mango"
6) "6"
7) "pear"
8) (nil)
預設情況下SORT使用被排序元素本身作為排序權重,如果使用BY選項,可以指定其他鍵的值作為排序權重。
SORT key [BY pattern]
pattern可以是包含*的字串,也可以是包含*和->的字串,與GET選項一樣。
下面的例子,根據*-price中儲存的價格對fruits集合中的水果進行排序。
redis> SORT fruits BY *-price
1) "pear"
2) "banana"
3) "mango"
4) "apple"
僅僅排序還不夠直觀,應該把*-price的價格也顯示出來,也就是使用兩個GET分別獲取水果的名稱和價格
redis> SORT fruits BY *-price GET # GET *-price
1) "pear"
2) (nil)
3) "banana"
4) "5"
5) "mango"
6) "6"
7) "apple"
8) "8"
11、DBSIZE:獲取資料庫包含的鍵數量
命令 | DBSIZE |
---|---|
效果 | 獲取當前資料庫包含的鍵數量 |
返回值 | 返回鍵的數量 |
12、MOVE:將鍵移動到另一個數據庫
命令 | MOVE key db |
---|---|
效果 | 將一個鍵從當前資料庫移到另一個數據庫。如果key不存在,或者目標資料庫存在與key同名的鍵,不會移動 |
返回值 | 移動成功返回1。未執行移動返回0 |
13、FLUSHDB、FLUSHALL:清空資料庫
命令 | FLUSHDB [ASYNC] |
---|---|
效果 | 清空當前資料庫。預設為同步,使用ASYNC選項將實際的資料庫清空操作放在後臺執行緒中非同步執行,以免阻塞伺服器 |
返回值 | 返回OK |
命令 | FLUSHALL [ASYNC] |
---|---|
效果 | 清空所有資料庫。預設為同步,使用ASYNC選項設為非同步執行。 |
返回值 | 返回OK |
14、SWAPDB:互換資料庫
命令 | SWAPDB index1 index2 |
---|---|
效果 | 對指定的兩個資料庫內所有資料互換 |
返回值 | 返回OK |
十、自動過期
Redis的自動過期特效能使特定鍵在指定時間後自動被移除。注意:自動過期只能對整個鍵進行設定,而不能對鍵中的某個元素進行設定。
1、EXPIRE、PEXPIRE:設定生存時間
EXPIRE、PEXPIRE可以為鍵設定一個生存時間(time to live,TTL),生存時間一旦被設定就會隨著時間流逝不斷減少,直到變成0後,鍵就會被移除。
一些命令,如SET等,在設定或覆蓋鍵時就能指定生存時間。
命令 | EXPIRE key seconds |
---|---|
效果 | 為鍵設定或更新一個秒級精度的生存時間。如果設定為非正數,將導致這個鍵被立即移除 |
返回值 | 返回1表示設定成功。如果鍵不存在,返回0 |
命令 | PEXPIRE key milliseconds |
---|---|
效果 | 為鍵設定或更新一個毫秒級精度的生存時間。如果設定為非正數,將導致這個鍵被立即移除 |
返回值 | 返回1表示設定成功。如果鍵不存在,返回0 |
使用覆蓋的方式可以清除鍵的生存時間,例如不帶EX選項的SET,GETSET,以及以STORE結尾的一些命令。而那些從字面意思上看只是更改值的命令,例如INCR,LPUSH,HSET等不會影響到生存時間。
2、EXPIREAT、PEXPIREAT:設定過期時間
過期時間是一個UNIX時間戳,鍵在這個時間戳到來後被移除。
命令 | EXPIREAT key timestamp |
---|---|
效果 | 設定或更新過期時間,timestamp是一個秒級的UNIX時間戳。如果設定為過去的時間,將導致這個鍵被立即移除 |
返回值 | 返回1表示設定成功。如果鍵不存在,返回0 |
命令 | PEXPIREAT key milliseconds-timestamp |
---|---|
效果 | 設定或更新過期時間,milliseconds-timestamp是一個毫秒級的UNIX時間戳。如果設定為過去的時間,將導致這個鍵被立即移除 |
返回值 | 返回1表示設定成功。如果鍵不存在,返回0 |
3、PERSIST:移除鍵的過期時間
命令 | PERSIST key |
---|---|
效果 | 移除鍵的過期時間,使其變為永久存在 |
返回值 | 返回1表示設定成功。如果鍵不存在或本來就沒有過期時間,返回0 |
4、TTL、PTTL:獲取鍵的剩餘生存時間
命令 | TTL key |
---|---|
效果 | 獲取鍵的剩餘生存時間(單位秒) |
返回值 | 返回以秒為單位的TTL(向下取整)。如果鍵不存在,返回-2。如果沒有設定過期時間,返回-1 |
命令 | PTTL key |
---|---|
效果 | 獲取鍵的剩餘生存時間(單位毫秒) |
返回值 | 返回以毫秒為單位的TTL。其他同TTL |
十一、總結及參考資料
本文介紹了Redis常見的五種資料結構(字串、雜湊、列表、集合、有序集合),以及點陣圖、Hyperloglog、地理座標,操作這些資料結構以及資料庫鍵的命令,並介紹了自動過期的特性。還有很多特性沒有涉及,如流(stream)這種Redis 5.0新增的資料結構、流水線和事務、釋出與訂閱等。進一步的學習,可以參考Redis官網的介紹以及其他資料,列舉如下:
1.Redis官網
2.Redis中文網
3.《Redis使用手冊》黃建巨集著 機械工業出版社出版