【Redis】基本數據類型及命令操作(超詳細)

来源:https://www.cnblogs.com/haoworld/archive/2019/09/26/redis-ji-ben-shu-ju-lei-xing-ji-ming-ling-cao-zuo-.html
-Advertisement-
Play Games

一、String1.1 概述1.2 相關命令列表1.3 命令示例二、List2.1 概述:2.2 相關命令列表:2.3 命令示例:2.4 鏈表結構的小技巧:三、HashSet3.1 概述3.2 相關命令列表3.3 命令示例四、Set4.1 概述:4.2 相關命令列表:4.3 命令示例:4.4 應用範... ...


一、String

可以直接看每一大節的命令示例部分,敲一遍就大體會了

1.1 概述

  • 字元串類型是Redis中最為基礎的數據存儲類型,它在Redis中是二進位安全的,這便意味著該類型可以接受任何格式的數據,如JPEG圖像數據或Json對象描述信息等。在Redis中字元串類型的Value最多可以容納的數據長度是512M。

1.2 相關命令列表

此後按照如下的排版進行講解:

[命令原型]
* [時間複雜度]   [命令描述]
* 返回值
  1. APPEND key value
    • O(1) 如果該Key已經存在,APPEND命令將參數Value的數據追加到已存在Value的末尾。如果該Key不存在,APPEND命令將會創建一個新的Key/Value。
    • 追加後Value的長度。
  2. DECR key
    • O(1) 將指定Key的Value原子性的遞減1。如果該Key不存在,其初始值為0,在decr之後其值為-1。如果Value的值不能轉換為整型值,如Hello,該操作將執行失敗並返回相應的錯誤信息。註意:該操作的取值範圍是64位有符號整型
    • 遞減後的Value值。
  3. INCR key
    • O(1) 將指定Key的Value原子性的遞增1。如果該Key不存在,其初始值為0,在incr之後其值為1。如果Value的值不能轉換為整型值,如Hello,該操作將執行失敗並返回相應的錯誤信息。註意:該操作的取值範圍是64位有符號整型。
    • 遞增後的Value值。
  4. DECRBY key decrement
    • O(1) 將指定Key的Value原子性的減少decrement。如果該Key不存在,其初始值為0,在decrby之後其值為-decrement。如果Value的值不能轉換為整型值,如Hello,該操作將執行失敗並返回相應的錯誤信息。註意:該操作的取值範圍是64位有符號整型。
    • 減少後的Value值。
  5. INCRBY key increment
    • O(1) 將指定Key的Value原子性的增加increment。如果該Key不存在,其初始值為0,在incrby之後其值為increment。如果Value的值不能轉換為整型值,如Hello,該操作將執行失敗並返回相應的錯誤信息。註意:該操作的取值範圍是64位有符號整型。
    • 增加後的Value值。
  6. GET key
    • O(1) 獲取指定Key的Value。如果與該Key關聯的Value不是string類型,Redis將返回錯誤信息,因為GET命令只能用於獲取string Value。
    • 與該Key相關的Value,如果該Key不存在,返回nil。
  7. SET key value
    • O(1) 設定該Key持有指定的字元串Value,如果該Key已經存在,則覆蓋其原有值。
    • 總是返回"OK"。
  8. GETSET key value
    • O(1) 原子性的設置該Key為指定的Value,同時返回該Key的原有值。和GET命令一樣,該命令也只能處理string Value,否則Redis將給出相關的錯誤信息。
    • 返回該Key的原有值,如果該Key之前並不存在,則返回nil。
  9. STRLEN key
    • O(1) 返回指定Key的字元值長度,如果Value不是string類型,Redis將執行失敗並給出相關的錯誤信息。
    • 返回指定Key的Value字元長度,如果該Key不存在,返回0。
  10. SETEX key seconds value
    • O(1) 原子性完成兩個操作,一是設置該Key的值為指定字元串,同時設置該Key在Redis伺服器中的存活時間(秒數)。該命令主要應用於Redis被當做Cache伺服器使用時。
  11. SETNX key value
    • O(1) 如果指定的Key不存在,則設定該Key持有指定字元串Value,此時其效果等價於SET命令。相反,如果該Key已經存在,該命令將不做任何操作並返回。
    • 1表示設置成功,否則0。
  12. SETRANGE key offset value
    • O(1) 替換指定Key的部分字元串值。從offset開始,替換的長度為該命令第三個參數value的字元串長度,其中如果offset的值大於該Key的原有值Value的字元串長度,Redis將會在Value的後面補齊(offset - strlen(value))數量的0x00,之後再追加新值。如果該鍵不存在,該命令會將其原值的長度假設為0,併在其後添補offset個0x00後再追加新值。鑒於字元串Value的最大長度為512M,因此offset的最大值為536870911。最後需要註意的是,如果該命令在執行時致使指定Key的原有值長度增加,這將會導致Redis重新分配足夠的記憶體以容納替換後的全部字元串,因此就會帶來一定的性能折損。
    • 修改後的字元串Value長度。
  13. GETRANGE key start end
    • O(1) 如果截取的字元串長度很短,我們可以該命令的時間複雜度視為O(1),否則就是O(N),這裡N表示截取的子字元串長度。該命令在截取子字元串時,將以閉區間的方式同時包含start(0表示第一個字元)和end所在的字元,如果end值超過Value的字元長度,該命令將只是截取從start開始之後所有的字元數據。
    • 子字元串
  14. SETBIT key offset value
    • O(1) 設置在指定Offset上BIT的值,該值只能為1或0,在設定後該命令返回該Offset上原有的BIT值。如果指定Key不存在,該命令將創建一個新值,併在指定的Offset上設定參數中的BIT值。如果Offset大於Value的字元長度,Redis將拉長Value值併在指定Offset上設置參數中的BIT值,中間添加的BIT值為0。最後需要說明的是Offset值必須大於0。
    • 在指定Offset上的BIT原有值。
  15. GETBIT key offset
    • O(1) 返回在指定Offset上BIT的值,0或1。如果Offset超過string value的長度,該命令將返回0,所以對於空字元串始終返回0。
    • 在指定Offset上的BIT值。
  16. MGET key [key ...]
    • O(N) N表示獲取Key的數量。返回所有指定Keys的Values,如果其中某個Key不存在,或者其值不為string類型,該Key的Value將返回nil。
    • 返回一組指定Keys的Values的列表。
  17. MSET key value [key value ...]
    • O(N) N表示指定Key的數量。該命令原子性的完成參數中所有key/value的設置操作,其具體行為可以看成是多次迭代執行SET命令。
    • 該命令不會失敗,始終返回OK。
  18. MSETNX key value [key value ...]
    • O(N) N表示指定Key的數量。該命令原子性的完成參數中所有key/value的設置操作,其具體行為可以看成是多次迭代執行SETNX命令。然而這裡需要明確說明的是,如果在這一批Keys中有任意一個Key已經存在了,那麼該操作將全部回滾,即所有的修改都不會生效。
    • 1表示所有Keys都設置成功,0則表示沒有任何Key被修改。

1.3 命令示例

  • 1.SET/GET/APPEND/STRLEN
/> redis-cli   #執行Redis客戶端工具。
redis 127.0.0.1:6379> exists mykey #判斷該鍵是否存在,存在返回1,否則返回0。
(integer) 0
redis 127.0.0.1:6379> append mykey "hello"   #該鍵並不存在,因此append命令返回當前Value的長度。
(integer) 5
redis 127.0.0.1:6379> append mykey " world" #該鍵已經存在,因此返回追加後Value的長度。
(integer) 11
redis 127.0.0.1:6379> get mykey  #通過get命令獲取該鍵,以判斷append的結果。
"hello world"
redis 127.0.0.1:6379> set mykey "this is a test" #通過set命令為鍵設置新值,並覆蓋原有值。
OK
redis 127.0.0.1:6379> get mykey
"this is a test"
redis 127.0.0.1:6379> strlen mykey   #獲取指定Key的字元長度,等效於C庫中strlen函數。
(integer) 14
  • 2.INCR/DECR/INCRBY/DECRBY
redis 127.0.0.1:6379> set mykey 20  #設置Key的值為20
OK
redis 127.0.0.1:6379> incr mykey    #該Key的值遞增1
(integer) 21
redis 127.0.0.1:6379> decr mykey  #該Key的值遞減1
(integer) 20
redis 127.0.0.1:6379> del mykey   #刪除已有鍵。
(integer) 1
redis 127.0.0.1:6379> decr mykey #對空值執行遞減操作,其原值被設定為0,遞減後的值為-1
(integer) -1
redis 127.0.0.1:6379> del mykey   
(integer) 1
redis 127.0.0.1:6379> incr mykey #對空值執行遞增操作,其原值被設定為0,遞增後的值為1
(integer) 1
redis 127.0.0.1:6379> set mykey hello #將該鍵的Value設置為不能轉換為整型的普通字元串。
OK
redis 127.0.0.1:6379> incr mykey #在該鍵上再次執行遞增操作時,Redis將報告錯誤信息。
(error) ERR value is not an integer or out of range
redis 127.0.0.1:6379> set mykey 10
OK
redis 127.0.0.1:6379> decrby mykey 5 
(integer) 5
redis 127.0.0.1:6379> incrby mykey 10
(integer) 15

  • 3.GETSET:
redis 127.0.0.1:6379> incr mycounter    #將計數器的值原子性的遞增1
(integer) 1
#在獲取計數器原有值的同時,並將其設置為新值,這兩個操作原子性的同時完成。
redis 127.0.0.1:6379> getset mycounter 0  
"1"
redis 127.0.0.1:6379> get mycounter  #查看設置後的結果。
"0"
  • 4.SETEX:
redis 127.0.0.1:6379> setex mykey 10 "hello"   #設置指定Key的過期時間為10秒。
OK    
#通過ttl命令查看一下指定Key的剩餘存活時間(秒數),0表示已經過期,-1表示永不過期。
redis 127.0.0.1:6379> ttl mykey                       
(integer) 4
redis 127.0.0.1:6379> get mykey    #在該鍵的存活期內我們仍然可以獲取到它的Value。
"hello"
redis 127.0.0.1:6379> ttl mykey       #該ttl命令的返回值顯示,該Key已經過期。
(integer) 0
redis 127.0.0.1:6379> get mykey        #獲取已過期的Key將返回nil。
(nil)

  • 5.SETNX:
redis 127.0.0.1:6379> del mykey    #刪除該鍵,以便於下麵的測試驗證。
(integer) 1
redis 127.0.0.1:6379> setnx mykey "hello"   #該鍵並不存在,因此該命令執行成功。
(integer) 1
redis 127.0.0.1:6379> setnx mykey "world" #該鍵已經存在,因此本次設置沒有產生任何效果。
(integer) 0
redis 127.0.0.1:6379> get mykey    #從結果可以看出,返回的值仍為第一次設置的值。
"hello"
  • 6.SETRANGE/GETRANGE:
redis 127.0.0.1:6379> set mykey "hello world"    #設定初始值。
OK
redis 127.0.0.1:6379> setrange mykey 6 dd    #從第六個位元組開始替換2個位元組(dd只有2個位元組)
(integer) 11
redis 127.0.0.1:6379> get mykey    #查看替換後的值。
"hello ddrld"
redis 127.0.0.1:6379> setrange mykey 20 dd   #offset已經超過該Key原有值的長度了,該命令將會在末尾補0。
(integer) 22
redis 127.0.0.1:6379> get mykey     #查看補0後替換的結果。
"hello ddrld\x00\x00\x00\x00\x00\x00\x00\x00\x00dd"
redis 127.0.0.1:6379> del mykey    #刪除該Key。
(integer) 1
redis 127.0.0.1:6379> setrange mykey 2 dd    #替換空值。
(integer) 4
redis 127.0.0.1:6379> get mykey      #查看替換空值後的結果。
"\x00\x00dd"   
redis 127.0.0.1:6379> set mykey "0123456789"   #設置新值。
OK
redis 127.0.0.1:6379> getrange mykey 1 2      #截取該鍵的Value,從第一個位元組開始,到第二個位元組結束。
"12"
redis 127.0.0.1:6379> getrange mykey 1 20   #20已經超過Value的總長度,因此將截取第一個位元組後面的所有位元組。
"123456789"
  • 7.SETBIT/GETBIT:
redis 127.0.0.1:6379> del mykey
(integer) 1
redis 127.0.0.1:6379> setbit mykey 7 1       #設置從0開始計算的第七位BIT值為1,返回原有BIT值0
(integer) 0
redis 127.0.0.1:6379> get mykey     #獲取設置的結果,二進位的0000 0001的十六進位值為0x01
"\x01"
redis 127.0.0.1:6379> setbit mykey 6 1       #設置從0開始計算的第六位BIT值為1,返回原有BIT值0
(integer) 0
redis 127.0.0.1:6379> get mykey  #獲取設置的結果,二進位的0000 0011的十六進位值為0x03
"\x03"
redis 127.0.0.1:6379> getbit mykey 6     #返回了指定Offset的BIT值。
(integer) 1
redis 127.0.0.1:6379> getbit mykey 10     #Offset已經超出了value的長度,因此返回0。
(integer) 0
  • 8.MSET/MGET/MSETNX:
redis 127.0.0.1:6379> mset key1 "hello" key2 "world"   #批量設置了key1和key2兩個鍵。
OK
redis 127.0.0.1:6379> mget key1 key2      #批量獲取了key1和key2兩個鍵的值。
1) "hello"
2) "world"
#批量設置了key3和key4兩個鍵,因為之前他們並不存在,所以該命令執行成功並返回1。
redis 127.0.0.1:6379> msetnx key3 "study" key4 "zhang" 
(integer) 1
redis 127.0.0.1:6379> mget key3 key4                   
1) "study"
2) "zhang"
#批量設置了key3和key5兩個鍵,但是key3已經存在,所以該命令執行失敗並返回0。
redis 127.0.0.1:6379> msetnx key3 "hello" key5 "world" 
(integer) 0
#批量獲取key3和key5,由於key5沒有設置成功,所以返回nil。
redis 127.0.0.1:6379> mget key3 key5                   
1) "study"
2) (nil)

二、List

2.1 概述:

  • 在Redis中,List類型是按照插入順序排序的字元串鏈表。和數據結構中的普通鏈表一樣,我們可以在其頭部(left)和尾部(right)添加新的元素。在插入時,如果該鍵並不存在,Redis將為該鍵創建一個新的鏈表。與此相反,如果鏈表中所有的元素均被移除,那麼該鍵也將會被從資料庫中刪除。List中可以包含的最大元素數量是4294967295。
  • 從元素插入和刪除的效率視角來看,如果我們是在鏈表的兩頭插入或刪除元素,這將會是非常高效的操作,即使鏈表中已經存儲了百萬條記錄,該操作也可以在常量時間內完成。然而需要說明的是,如果元素插入或刪除操作是作用於鏈表中間,那將會是非常低效的。相信對於有良好數據結構基礎的開發者而言,這一點並不難理解。

2.2 相關命令列表:

此後按照如下的排版進行講解:

[命令原型]
* [時間複雜度]   [命令描述]
* 返回值
  1. LPUSH key value [value ...]
    • O(1) 在指定Key所關聯的List Value的頭部插入參數中給出的所有Values。如果該Key不存在,該命令將在插入之前創建一個與該Key關聯的空鏈表,之後再將數據從鏈表的頭部插入。如果該鍵的Value不是鏈表類型,該命令將返回相關的錯誤信息。
    • 插入後鏈表中元素的數量。
  2. LPUSHX key value
    • O(1) 僅有當參數中指定的Key存在時,該命令才會在其所關聯的List Value的頭部插入參數中給出的Value,否則將不會有任何操作發生。
    • 插入後鏈表中元素的數量。
  3. LRANGE key start stop
    • O(S+N) 時間複雜度中的S為start參數表示的偏移量,N表示元素的數量。該命令的參數start和end都是0-based。即0表示鏈表頭部(leftmost)的第一個元素。其中start的值也可以為負值,-1將表示鏈表中的最後一個元素,即尾部元素,-2表示倒數第二個並以此類推。該命令在獲取元素時,start和end位置上的元素也會被取出。如果start的值大於鏈表中元素的數量,空鏈表將會被返回。如果end的值大於元素的數量,該命令則獲取從start(包括start)開始,鏈表中剩餘的所有元素。
    • 返回指定範圍內元素的列表。
  4. LPOP key
    • O(1) 返回並彈出指定Key關聯的鏈表中的第一個元素,即頭部元素
    • 如果Key不存,返回nil。
  5. LLEN key
    • O(1) 返回指定Key關聯的鏈表中元素的數量,如果該Key不存在,則返回0。如果與該Key關聯的Value的類型不是鏈表,則返回相關的錯誤信息。
    • 鏈表中元素的數量。
  6. LREM key count value
    • O(N) 時間複雜度中N表示鏈表中元素的數量。在指定Key關聯的鏈表中,刪除前count個值等於value的元素。如果count大於0,從頭向尾遍歷並刪除,如果count小於0,則從尾向頭遍歷並刪除。如果count等於0,則刪除鏈表中所有等於value的元素。如果指定的Key不存在,則直接返回0
    • 返回被刪除的元素數量。
  7. LSET key index value
    • O(N) 時間複雜度中N表示鏈表中元素的數量。但是設定頭部或尾部的元素時,其時間複雜度為O(1)。設定鏈表中指定位置的值為新值,其中0表示第一個元素,即頭部元素,-1表示尾部元素。
    • 如果索引值Index超出了鏈表中元素的數量範圍,該命令將返回相關的錯誤信息。
  8. LINDEX key index
    • O(N) 時間複雜度中N表示在找到該元素時需要遍歷的元素數量。對於頭部或尾部元素,其時間複雜度為O(1)。該命令將返回鏈表中指定位置(index)的元素,index是0-based,表示頭部元素,如果index為-1,表示尾部元素。如果與該Key關聯的不是鏈表,該命令將返回相關的錯誤信息。
    • 返回請求的元素,如果index超出範圍,則返回nil。
  9. LTRIM key start stop
    • O(N) N表示被刪除的元素數量。該命令將僅保留指定範圍內的元素,從而保證鏈接中的元素數量相對恆定。start和stop參數都是0-based,0表示頭部元素。和其他命令一樣,start和stop也可以為負值,-1表示尾部元素。
    • 如果start大於鏈表的尾部,或start大於stop,該命令不錯報錯,而是返回一個空的鏈表,與此同時該Key也將被刪除。如果stop大於元素的數量,則保留從start開始剩餘的所有元素。
  10. LINSERT key BEFORE|AFTER pivot value
    • O(N) 時間複雜度中N表示在找到該元素pivot之前需要遍歷的元素數量。這樣意味著如果pivot位於鏈表的頭部或尾部時,該命令的時間複雜度為O(1)。該命令的功能是在pivot元素的前面或後面插入參數中的元素value。如果Key不存在,該命令將不執行任何操作。如果與Key關聯的Value類型不是鏈表,相關的錯誤信息將被返回。
    • 成功插入後鏈表中元素的數量,如果沒有找到pivot,返回-1,如果key不存在,返回0。
  11. RPUSH key value [value ...] O
    • (1) 在指定Key所關聯的List Value的尾部插入參數中給出的所有Values。如果該Key不存在,該命令將在插入之前創建一個與該Key關聯的空鏈表,之後再將數據從鏈表的尾部插入。如果該鍵的Value不是鏈表類型,該命令將返回相關的錯誤信息。
    • 插入後鏈表中元素的數量。
  12. RPUSHX key value
    • O(1) 僅有當參數中指定的Key存在時,該命令才會在其所關聯的List Value的尾部插入參數中給出的Value,否則將不會有任何操作發生。
    • 插入後鏈表中元素的數量。
  13. RPOP key
    • O(1) 返回並彈出指定Key關聯的鏈表中的最後一個元素,即尾部元素,。如果該Key不存,返回nil。
    • 鏈表尾部的元素。
  14. RPOPLPUSH source destination
    • O(1) 原子性的從與source鍵關聯的鏈表尾部彈出一個元素,同時再將彈出的元素插入到與destination鍵關聯的鏈表的頭部。如果source鍵不存在,該命令將返回nil,同時不再做任何其它的操作了。如果source和destination是同一個鍵,則相當於原子性的將其關聯鏈表中的尾部元素移到該鏈表的頭部。
    • 返回彈出和插入的元素。

2.3 命令示例:

  • 1. LPUSH/LPUSHX/LRANGE
/> redis-cli    ## 在Shell提示符下啟動redis客戶端工具。
redis 127.0.0.1:6379> del mykey
(integer) 1
## mykey鍵並不存在,該命令會創建該鍵及與其關聯的List,
## 之後在將參數中的values從左到右依次插入。
redis 127.0.0.1:6379> lpush mykey a b c d
(integer) 4
## 取從位置0開始到位置2結束的3個元素。
redis 127.0.0.1:6379> lrange mykey 0 2
1) "d"
2) "c"
3) "b"
## 取鏈表中的全部元素,其中0表示第一個元素,-1表示最後一個元素。
redis 127.0.0.1:6379> lrange mykey 0 -1
1) "d"
2) "c"
3) "b"
4) "a"
## mykey2鍵此時並不存在,因此該命令將不會進行任何操作,其返回值為0。
redis 127.0.0.1:6379> lpushx mykey2 e
(integer) 0
## 可以看到mykey2沒有關聯任何List Value。
redis 127.0.0.1:6379> lrange mykey2 0 -1
(empty list or set)
## mykey鍵此時已經存在,所以該命令插入成功,並返回鏈表中當前元素的數量。
redis 127.0.0.1:6379> lpushx mykey e
(integer) 5
## 獲取該鍵的List Value的頭部元素。
redis 127.0.0.1:6379> lrange mykey 0 0
1) "e"
  • 2. LPOP/LLEN
redis 127.0.0.1:6379> lpush mykey a b c d
(integer) 4
redis 127.0.0.1:6379> lpop mykey
"d"
redis 127.0.0.1:6379> lpop mykey
"c"
## 在執行lpop命令兩次後,鏈表頭部的兩個元素已經被彈出,
## 此時鏈表中元素的數量是2
redis 127.0.0.1:6379> llen mykey
(integer) 2
  • 3. LREM/LSET/LINDEX/LTRIM
## 為後面的示例準備測試數據。
redis 127.0.0.1:6379> lpush mykey a b c d a c
(integer) 6
## 從頭部(left)向尾部(right)變數鏈表,
## 刪除2個值等於a的元素,返回值為實際刪除的數量。
redis 127.0.0.1:6379> lrem mykey 2 a
(integer) 2
## 看出刪除後鏈表中的全部元素。
redis 127.0.0.1:6379> lrange mykey 0 -1
1) "c"
2) "d"
3) "c"
4) "b"
## 獲取索引值為1(頭部的第二個元素)的元素值。
redis 127.0.0.1:6379> lindex mykey 1
"d"
## 將索引值為1(頭部的第二個元素)的元素值設置為新值e。
redis 127.0.0.1:6379> lset mykey 1 e
OK
## 查看是否設置成功。
redis 127.0.0.1:6379> lindex mykey 1
"e"
## 索引值6超過了鏈表中元素的數量,該命令返回nil。
redis 127.0.0.1:6379> lindex mykey 6
(nil)
## 設置的索引值6超過了鏈表中元素的數量,設置失敗,該命令返回錯誤信息。
redis 127.0.0.1:6379> lset mykey 6 hh
(error) ERR index out of range
## 僅保留索引值0到2之間的3個元素,註意第0個和第2個元素均被保留。
redis 127.0.0.1:6379> ltrim mykey 0 2
OK
## 查看trim後的結果。
redis 127.0.0.1:6379> lrange mykey 0 -1
1) "c"
2) "e"
3) "c"

  • 4. LINSERT
##刪除該鍵便於後面的測試。
redis 127.0.0.1:6379> del mykey
(integer) 1
##為後面的示例準備測試數據。
redis 127.0.0.1:6379> lpush mykey a b c d e
(integer) 5
##在a的前面插入新元素a1。
redis 127.0.0.1:6379> linsert mykey before a a1
(integer) 6
##查看是否插入成功,從結果看已經插入。註意lindex的index值是0-based。
redis 127.0.0.1:6379> lindex mykey 0
"e"
##在e的後面插入新元素e2,從返回結果看已經插入成功。
redis 127.0.0.1:6379> linsert mykey after e e2
(integer) 7
##再次查看是否插入成功。
redis 127.0.0.1:6379> lindex mykey 1
"e2"
##在不存在的元素之前或之後插入新元素,該命令操作失敗,並返回-1。
redis 127.0.0.1:6379> linsert mykey after k a
(integer) -1
##為不存在的Key插入新元素,該命令操作失敗,返回0。
redis 127.0.0.1:6379> linsert mykey1 after a a2
(integer) 0
  • 5. RPUSH/RPUSHX/RPOP/RPOPLPUSH
##刪除該鍵,以便於後面的測試。
redis 127.0.0.1:6379> del mykey
(integer) 1
##從鏈表的尾部插入參數中給出的values,插入順序是從左到右依次插入。
redis 127.0.0.1:6379> rpush mykey a b c d
(integer) 4
##通過lrange的可以獲悉rpush在插入多值時的插入順序。
redis 127.0.0.1:6379> lrange mykey 0 -1
1) "a"
2) "b"
3) "c"
4) "d"
##該鍵已經存在並且包含4個元素,rpushx命令將執行成功,
##並將元素e插入到鏈表的尾部。
redis 127.0.0.1:6379> rpushx mykey e
(integer) 5
## 通過lindex命令可以看出之前的rpushx命令確實執行成功
## 因為索引值為4的元素已經是新元素了。
redis 127.0.0.1:6379> lindex mykey 4
"e"
##由於mykey2鍵並不存在,因此該命令不會插入數據,其返回值為0。
redis 127.0.0.1:6379> rpushx mykey2 e
(integer) 0
##在執行rpoplpush命令前,先看一下mykey中鏈表的元素有哪些,
##註意他們的位置關係。
redis 127.0.0.1:6379> lrange mykey 0 -1
1) "a"
2) "b"
3) "c"
4) "d"
5) "e"
##將mykey的尾部元素e彈出,同時再插入到mykey2的頭部(原子性的完成這兩步操作)。
redis 127.0.0.1:6379> rpoplpush mykey mykey2
"e"
##通過lrange命令查看mykey在彈出尾部元素後的結果。
redis 127.0.0.1:6379> lrange mykey 0 -1
1) "a"
2) "b"
3) "c"
4) "d"
##通過lrange命令查看mykey2在插入元素後的結果。
redis 127.0.0.1:6379> lrange mykey2 0 -1
1) "e"
##將source和destination設為同一鍵,將mykey中的尾部元素移到其頭部。
redis 127.0.0.1:6379> rpoplpush mykey mykey
"d"
##查看移動結果。
redis 127.0.0.1:6379> lrange mykey 0 -1
1) "d"
2) "a"
3) "b"
4) "c"

2.4 鏈表結構的小技巧:

  • 針對鏈表結構的Value,Redis在其官方文檔中給出了一些實用技巧,如RPOPLPUSH命令,下麵給出具體的解釋。
  • Redis鏈表經常會被用於消息隊列的服務,以完成多程式之間的消息交換。假設一個應用程式正在執行LPUSH操作向鏈表中添加新的元素,我們通常將這樣的程式稱之為"生產者(Producer)",而另外一個應用程式正在執行RPOP操作從鏈表中取出元素,我們稱這樣的程式為"消費者(Consumer)"。如果此時,消費者程式在取出消息元素後立刻崩潰,由於該消息已經被取出且沒有被正常處理,那麼我們就可以認為該消息已經丟失,由此可能會導致業務數據丟失,或業務狀態的不一致等現象的發生。然而通過使用RPOPLPUSH命令,消費者程式在從主消息隊列中取出消息之後再將其插入到備份隊列中,直到消費者程式完成正常的處理邏輯後再將該消息從備份隊列中刪除。同時我們還可以提供一個守護進程,當發現備份隊列中的消息過期時,可以重新將其再放回到主消息隊列中,以便其它的消費者程式繼續處理。

三、Hashes

3.1 概述

  • 我們可以將Redis中的Hashes類型看成具有String Key和String Value的map容器。所以該類型非常適合於存儲值對象的信息。如Username、Password和Age等。如果Hash中包含很少的欄位,那麼該類型的數據也將僅占用很少的磁碟空間。每一個Hash可以存儲4294967295個鍵值對。

3.2 相關命令列表

此後按照如下的排版進行講解:

[命令原型]
* [時間複雜度]   [命令描述]
* 返回值
  1. HSET key field value

    • O(1) 為指定的Key設定Field/Value對,如果Key不存在,該命令將創建新Key以參數中的Field/Value對,如果參數中的Field在該Key中已經存在,則用新值覆蓋其原有值。
    • 1表示新的Field被設置了新值,0表示Field已經存在,用新值覆蓋原有值。
  2. HGET key field

    • O(1) 返回指定Key中指定Field的關聯值。
    • 返回參數中Field的關聯值,如果參數中的Key或Field不存,返回nil。
  3. HEXISTS key field

    • O(1) 判斷指定Key中的指定Field是否存在。
    • 1表示存在,0表示參數中的Field或Key不存在。
  4. HLEN key

    • O(1) 獲取該Key所包含的Field的數量。
    • 返回Key包含的Field數量,如果Key不存在,返回0。
  5. HDEL key field [field ...] O(N) 時間複雜度中的N表示參數中待刪除的欄位數量。從指定Key的Hashes Value中刪除參數中指定的多個欄位,如果不存在的欄位將被忽略。如果Key不存在,則將其視為空Hashes,並返回0.

    • 實際刪除的Field數量。
  6. HSETNX key field value

    • O(1) 只有當參數中的Key或Field不存在的情況下,為指定的Key設定Field/Value對,否則該命令不會進行任何操作。
    • 1表示新的Field被設置了新值,0表示Key或Field已經存在,該命令沒有進行任何操作。
  7. HINCRBY key field increment

    • O(1) 增加指定Key中指定Field關聯的Value的值。如果Key或Field不存在,該命令將會創建一個新Key或新Field,並將其關聯的Value初始化為0,之後再指定數字增加的操作。該命令支持的數字是64位有符號整型,即increment可以負數。
    • 返回運算後的值。
  8. HGETALL key

    • O(N) 時間複雜度中的N表示Key包含的Field數量。獲取該鍵包含的所有Field/Value。其返回格式為一個Field、一個Value,並以此類推。
    • Field/Value的列表。
  9. HKEYS key

    • O(N) 時間複雜度中的N表示Key包含的Field數量。返回指定Key的所有Fields名。
    • Field的列表。
  10. HVALS key

    • O(N) 時間複雜度中的N表示Key包含的Field數量。返回指定Key的所有Values名。
    • Value的列表。
  11. HMGET key field [field ...]

    • O(N) 時間複雜度中的N表示請求的Field數量。獲取和參數中指定Fields關聯的一組Values。
    • 如果請求的Field不存在,其值返回nil。如果Key不存在,該命令將其視為空Hash,因此返回一組nil。 返回和請求Fields關聯的一組Values,其返回順序等同於Fields的請求順序。
  12. HMSET key field value [field value ...] * O(N) 時間複雜度中的N表示被設置的Field數量。逐對依次設置參數中給出的Field/Value對。如果其中某個Field已經存在,則用新值覆蓋原有值。如果Key不存在,則創建新Key,同時設定參數中的Field/Value。

3.3 命令示例

  • 1. HSET/HGET/HDEL/HEXISTS/HLEN/HSETNX
## 在Shell命令行啟動Redis客戶端程式
/> redis-cli
## 給鍵值為myhash的鍵設置欄位為field1,值為study。
redis 127.0.0.1:6379> hset myhash field1 "study"
(integer) 1
## 獲取鍵值為myhash,欄位為field1的值。
redis 127.0.0.1:6379> hget myhash field1
"study"
## myhash鍵中不存在field2欄位,因此返回nil。
redis 127.0.0.1:6379> hget myhash field2
(nil)
## 給myhash關聯的Hashes值添加一個新的欄位field2,其值為zhang。
redis 127.0.0.1:6379> hset myhash field2 "zhang"
(integer) 1
## 獲取myhash鍵的欄位數量。
redis 127.0.0.1:6379> hlen myhash
(integer) 2
## 判斷myhash鍵中是否存在欄位名為field1的欄位,由於存在,返回值為1。
redis 127.0.0.1:6379> hexists myhash field1
(integer) 1
## 刪除myhash鍵中欄位名為field1的欄位,刪除成功返回1。
redis 127.0.0.1:6379> hdel myhash field1
(integer) 1
## 再次刪除myhash鍵中欄位名為field1的欄位,
## 由於上一條命令已經將其刪除,因為沒有刪除,返回0。
redis 127.0.0.1:6379> hdel myhash field1
(integer) 0
## 判斷myhash鍵中是否存在field1欄位,由於上一條命令已經將其刪除,因為返回0。
redis 127.0.0.1:6379> hexists myhash field1
(integer) 0
## 通過hsetnx命令給myhash添加新欄位field1,
## 其值為zhang,因為該欄位已經被刪除,所以該命令添加成功並返回1。
redis 127.0.0.1:6379> hsetnx myhash field1 study
(integer) 1
## 由於myhash的field1欄位已經通過上一條命令添加成功,
## 因為本條命令不做任何操作後返回0。
redis 127.0.0.1:6379> hsetnx myhash field1 study
(integer) 0
  • 2. HINCRBY
## 刪除該鍵,便於後面示例的測試。
redis 127.0.0.1:6379> del myhash
(integer) 1
## 準備測試數據,該myhash的field欄位設定值1。
redis 127.0.0.1:6379> hset myhash field 5
(integer) 1
## 給myhash的field欄位的值加1,返回加後的結果。
redis 127.0.0.1:6379> hincrby myhash field 1
(integer) 6
## 給myhash的field欄位的值加-1,返回加後的結果。
redis 127.0.0.1:6379> hincrby myhash field -1
(integer) 5
## 給myhash的field欄位的值加-10,返回加後的結果。
redis 127.0.0.1:6379> hincrby myhash field -10
(integer) -5   
  • 3. HGETALL/HKEYS/HVALS/HMGET/HMSET
## 刪除該鍵,便於後面示例測試。
redis 127.0.0.1:6379> del myhash
(integer) 1
## 為該鍵myhash,一次性設置多個欄位,
## 分別是field1 = "hello", field2 = "world"。
redis 127.0.0.1:6379> hmset myhash field1 "hello" field2 "world"
OK
## 獲取myhash鍵的多個欄位,其中field3並不存在,
## 因為在返回結果中與該欄位對應的值為nil。
redis 127.0.0.1:6379> hmget myhash field1 field2 field3
1) "hello"
2) "world"
3) (nil)
## 返回myhash鍵的所有欄位及其值,從結果中可以看出,他們是逐對列出的。
redis 127.0.0.1:6379> hgetall myhash
1) "field1"
2) "hello"
3) "field2"
4) "world"
## 僅獲取myhash鍵中所有欄位的名字。
redis 127.0.0.1:6379> hkeys myhash
1) "field1"
2) "field2"
## 僅獲取myhash鍵中所有欄位的值。
redis 127.0.0.1:6379> hvals myhash
1) "hello"
2) "world"

四、Set

4.1 概述:

  • 在Redis中,我們可以將Set類型看作為沒有排序的字元集合,和List類型一樣,我們也可以在該類型的數據值上執行添加、刪除或判斷某一元素是否存在等操作。需要說明的是,這些操作的時間複雜度為O(1),即常量時間內完成次操作。Set可包含的最大元素數量是4294967295。
  • 和List類型不同的是,Set集合中不允許出現重覆的元素,這一點和C++標準庫中的set容器是完全相同的。換句話說,如果多次添加相同元素,Set中將僅保留該元素的一份拷貝。和List類型相比,Set類型在功能上還存在著一個非常重要的特性,即在伺服器端完成多個Sets之間的聚合計算操作,如unions、intersections和differences。由於這些操作均在服務端完成,因此效率極高,而且也節省了大量的網路IO開銷。

4.2 相關命令列表:

此後按照如下的排版進行講解:

[命令原型]
* [時間複雜度]   [命令描述]
* 返回值
  1. SADD key member [member ...]

    • O(N) 時間複雜度中的N表示操作的成員數量。如果在插入的過程用,參數中有的成員在Set中已經存在,該成員將被忽略,而其它成員仍將會被正常插入。如果執行該命令之前,該Key並不存在,該命令將會創建一個新的Set,此後再將參數中的成員陸續插入。如果該Key的Value不是Set類型,該命令將返回相關的錯誤信息。
    • 本次操作實際插入的成員數量。
  2. SCARD key

    • O(1) 獲取Set中成員的數量。
    • 返回Set中成員的數量,如果該Key並不存在,返回0。
  3. SISMEMBER key member

    • O(1) 判斷參數中指定成員是否已經存在於與Key相關聯的Set集合中。
    • 1表示已經存在,0表示不存在,或該Key本身並不存在。
  4. SMEMBERS key

    • O(N) 時間複雜度中的N表示Set中已經存在的成員數量。獲取與該Key關聯的Set中所有的成員。
    • 返回Set中所有的成員。
  5. SPOP key

    • O(1) 隨機的移除並返回Set中的某一成員。 由於Set中元素的佈局不受外部控制,因此無法像List那樣確定哪個元素位於Set的頭部或者尾部。
    • 返回移除的成員,如果該Key並不存在,則返回nil。
  6. SREM key member [member ...]

    • O(N) 時間複雜度中的N表示被刪除的成員數量。從與Key關聯的Set中刪除參數中指定的成員,不存在的參數成員將被忽略,如果該Key並不存在,將視為空Set處理。
    • 從Set中實際移除的成員數量,如果沒有則返回0。
  7. SRANDMEMBER key

    • O(1) 和SPOP一樣,隨機的返回Set中的一個成員,不同的是該命令並不會刪除返回的成員。
    • 返回隨機位置的成員,如果Key不存在則返回nil。
  8. SMOVE source destination member

    • O(1) 原子性的將參數中的成員從source鍵移入到destination鍵所關聯的Set中。因此在某一時刻,該成員或者出現在source中,或者出現在destination中。如果該成員在source中並不存在,該命令將不會再執行任何操作並返回0,否則,該成員將從source移入到destination。如果此時該成員已經在destination中存在,那麼該命令僅是將該成員從source中移出。如果和Key關聯的Value不是Set,將返回相關的錯誤信息。
    • 1表示正常移動,0表示source中並不包含參數成員。
  9. SDIFF key [key ...]

    • O(N) 時間複雜度中的N表示所有Sets中成員的總數量。返回參數中第一個Key所關聯的Set和其後所有Keys所關聯的Sets中成員的差異。如果Key不存在,則視為空Set。
    • 差異結果成員的集合。
  10. SDIFFSTORE destination key [key ...]

    • O(N) 該命令和SDIFF命令在功能上完全相同,兩者之間唯一的差別是SDIFF返回差異的結果成員,而該命令將差異成員存儲在destination關聯的Set中。如果destination鍵已經存在,該操作將覆蓋它的成員。
    • 返回差異成員的數量。
  11. SINTER key [key ...]

    • O(N*M) 時間複雜度中的N表示最小Set中元素的數量,M則表示參數中Sets的數量。該命令將返回參數中所有Keys關聯的Sets中成員的交集。因此如果參數中任何一個Key關聯的Set為空,或某一Key不存在,那麼該命令的結果將為空集。
    • 交集結果成員的集合。
  12. SINTERSTORE destination key [key ...]

    • O(N*M) 該命令和SINTER命令在功能上完全相同,兩者之間唯一的差別是SINTER返回交集的結果成員,而該命令將交集成員存儲在destination關聯的Set中。如果destination鍵已經存在,該操作將覆蓋它的成員。
    • 返回交集成員的數量。
  13. SUNION key [key ...]

    • O(N) 時間複雜度中的N表示所有Sets中成員的總數量。該命令將返回參數中所有Keys關聯的Sets中成員的並集。 並集結果成員的集合。
  14. SUNIONSTORE destination key [key ...]

    • O(N) 該命令和SUNION命令在功能上完全相同,兩者之間唯一的差別是SUNION返回並集的結果成員,而該命令將並集成員存儲在destination關聯的Set中。如果destination鍵已經存在,該操作將覆蓋它的成員。
    • 返回並集成員的數量。

4.3 命令示例:

  • 1. 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

  • 2. SPOP/SREM/SRANDMEMBER/SMOVE
## 刪除該鍵,便於後面的測試。
redis 127.0.0.1:6379> del myset
(integer) 1
## 為後面的示例準備測試數據。
redis 127.0.0.1:6379> sadd myset a b c d
(integer) 4
## 查看Set中成員的位置。
redis 127.0.0.1:6379> smembers myset
1) "c"
2) "d"
3) "a"
4) "b"
## 從結果可以看出,該命令確實是隨機的返回了某一成員。
redis 127.0.0.1:6379> srandmember myset
"c"
## Set中尾部的成員b被移出並返回,事實上b並不是之前插入的第一個或最後一個成員。
redis 127.0.0.1:6379> spop myset
"b"
## 查看移出後Set的成員信息。
redis 127.0.0.1:6379> smembers myset
1) "c"
2) "d"
3) "a"
## 從Set中移出a、d和f三個成員,其中f並不存在,因此只有a和d兩個成員被移出,返回為2。
redis 127.0.0.1:6379> srem myset a d f
(integer) 2
## 查看移出後的輸出結果。
redis 127.0.0.1:6379> smembers myset
1) "c"
## 為後面的smove命令準備數據。
redis 127.0.0.1:6379> sadd myset a b
(integer) 2
redis 127.0.0.1:6379> sadd myset2 c d
(integer) 2
## 將a從myset移到myset2,從結果可以看出移動成功。
redis 127.0.0.1:6379> smove myset myset2 a
(integer) 1
## 再次將a從myset移到myset2,由於此時a已經不是myset的成員了,
## 因此移動失敗並返回0。
redis 127.0.0.1:6379> smove myset myset2 a
(integer) 0
## 分別查看myset和myset2的成員,確認移動是否真的成功。
redis 127.0.0.1:6379> smembers myset
1) "b"
redis 127.0.0.1:6379> smembers myset2
1) "c"
2) "d"
3) "a"

  • 3. SDIFF/SDIFFSTORE/SINTER/SINTERSTORE
##為後面的命令準備測試數據。
redis 127.0.0.1:6379> sadd myset a b c d
(integer) 4
redis 127.0.0.1:6379> sadd myset2 c
(integer) 1
redis 127.0.0.1:6379> sadd myset3 a c e
(integer) 3
##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
(integer) 2
##查看一下sdiffstore的操作結果。
redis 127.0.0.1:6379> smembers diffkey
1) "d"
2) "b"
##從之前準備的數據就可以看出,這三個Set的成員交集只有c。
redis 127.0.0.1:6379> sinter myset myset2 myset3
1) "c"
##將3個集合中的交集成員存儲到與interkey關聯的Set中,並返回交集成員的數量。
redis 127.0.0.1:6379> sinterstore interkey myset myset2 myset3
(integer) 1
##查看一下sinterstore的操作結果。
redis 127.0.0.1:6379> smembers interkey
1) "c"
##獲取3個集合中的成員的並集。    
redis 127.0.0.1:6379> sunion myset myset2 myset3
1) "b"
2) "c"
3) "d"
4) "e"
5) "a"
##將3個集合中成員的並集存儲到unionkey關聯的set中,並返回並集成員的數量。
redis 127.0.0.1:6379> sunionstore unionkey myset myset2 myset3
(integer) 5
##查看一下suiionstore的操作結果。
redis 127.0.0.1:6379> smembers unionkey
1) "b"
2) "c"
3) "d"
4) "e"
5) "a"

4.4 應用範圍:

  • 可以使用Redis的Set數據類型跟蹤一些唯一性數據,比如訪問某一博客的唯一IP地址信息。對於此場景,我們僅需在每次訪問該博客時將訪問者的IP存入Redis中,Set數據類型會自動保證IP地址的唯一性。
  • 充分利用Set類型的服務端聚合操作方便、高效的特性,可以用於維護數據對象之間的關聯關係。比如所有購買某一電子設備的客戶ID被存儲在一個指定的Set中,而購買另外一種電子產品的客戶ID被存儲在另外一個Set中,如果此時我們想獲取有哪些客戶同時購買了這兩種商品時,Set的intersections命令就可以充分發揮它的方便和效率的優勢了。

五、Sorted-Sets

5.1 概述:

  • Sorted-Sets和Sets類型極為相似,它們都是字元串的集合,都不允許重覆的成員出現在一個Set中。它們之間的主要差別是Sorted-Sets中的每一個成員都會有一個分數(score)與之關聯,Redis正是通過分數來為集合中的成員進行從小到大的排序。然而需要額外指出的是,儘管Sorted-Sets中的成員必須是唯一的,但是分數(score)卻是可以重覆的。
  • 在Sorted-Set中添加、刪除或更新一個成員都是非常快速的操作,其時間複雜度為集合中成員數量的對數。由於Sorted-Sets中的成員在集合中的位置是有序的,因此,即便是訪問位於集合中部的成員也仍然是非常高效的。事實上,Redis所具有的這一特征在很多其它類型的資料庫中是很難實現的,換句話說,在該點上要想達到和Redis同樣的高效,在其它資料庫中進行建模是非常困難的。

5.2 相關命令列表:

此後按照如下的排版進行講解:

[命令原型]
* [時間複雜度]   [命令描述]
* 返回值
  1. ZADD key score member [score] [member]

    • O(log(N)) 時間複雜度中的N表示Sorted-Sets中成員的數量。添加參數中指定的所有成員及其分數到指定key的Sorted-Set中,在該命令中我們可以指定多組score/member作為參數。如果在添加時參數中的某一成員已經存在,該命令將更新此成員的分數為新值,同時再將該成員基於新值重新排序。如果鍵不存在,該命令將為該鍵創建一個新的Sorted-Sets Value,並將score/member對插入其中。如果該鍵已經存在,但是與其關聯的Value不是Sorted-Sets類型,相關的錯誤信息將被返回。
    • 本次操作實際插入的成員數量。
  2. ZCARD key

    • O(1) 獲取與該Key相關聯的Sorted-Sets中包含的成員數量。
    • 返回Sorted-Sets中的成員數量,如果該Key不存在,返回0。
  3. ZCOUNT key min max

    • O(log(N)+M) 該命令用於獲取分數(score)在min和max之間的成員數量。針對min和max參數需要額外說明的是,-inf和+inf分別表示Sorted-Sets中分數的最高值和最低值。預設情況下,min和max表示的範圍是閉區間範圍,即min <= score <= max內的成員將被返回。然而我們可以通過在min和max的前面添加"("字元來表示開區間,如(min max表示min < score <= max,而(min (max表示min < score < max。
    • 分數指定範圍內成員的數量。
  4. ZINCRBY key increment member

    • O(log(N)) 該命令將為指定Key中的指定成員增加指定的分數。如果成員不存在,該命令將添加該成員並假設其初始分數為0,此後再將其分數加上increment。如果Key不存,該命令將創建該Key及其關聯的Sorted-Sets,並包含參數指定的成員,其分數為increment參數。如果與該Key關聯的不是Sorted-Sets類型,相關的錯誤信息將被返回。
    • 以字元串形式表示的新分數。
  5. ZRANGE key start stop [WITHSCORES]

    • O(log(N)+M) 時間複雜度中的N表示Sorted-Set中成員的數量,M則表示返回的成員數量。該命令返回順序在參數start和stop指定範圍內的成員,這裡start和stop參數都是0-based,即0表示第一個成員,-1表示最後一個成員。如果start大於該Sorted-Set中的最大索引值,或start > stop,此時一個空集合將被返回。如果stop大於最大索引值,該命令將返回從start到集合的最後一個成員。如果命令中帶有可選參數WITHSCORES選項,該命令在返回的結果中將包含每個成員的分數值,如value1,score1,value2,score2...。  
      • 返回索引在start和stop之間的成員列表。
  6. ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]

    • O(log(N)+M) 該命令將返回分數在min和max之間的所有成員,即滿足表達式min <= score <= max的成員,其中返回的成員是按照其分數從低到高的順序返回,如果成員具有相同的分數,則按成員的字典順序返回。可選參數LIMIT用於限制返回成員的數量範圍。可選參數offset表示從符合條件的第offset個成員開始返回,同時返回count個成員。可選參數WITHSCORES的含義參照ZRANGE中該選項的說明。最後需要說明的是參數中min和max的規則可參照命令ZCOUNT。
    • 返回分數在指定範圍內的成員列表。
  7. ZRANK key member

    • O(log(N)) 時間複雜度中的N表示Sorted-Set中成員的數量。Sorted-Set中的成員都是按照分數從低到高的順序存儲,該命令將返回參數中指定成員的位置值,其中0表示第一個成員,它是Sorted-Set中分數最低的成員。
    • 如果該成員存在,則返回它的位置索引值。否則返回nil。
  8. ZREM key member [member ...]

    • O(M log(N)) 時間複雜度中N表示Sorted-Set中成員的數量,M則表示被刪除的成員數量。該命令將移除參數中指定的成員,其中不存在的成員將被忽略。如果與該Key關聯的Value不是Sorted-Set,相應的錯誤信息將被返回。
    • 實際被刪除的成員數量。
  9. ZREVRANGE key start stop [WITHSCORES]

    • O(log(N)+M) 時間複雜度中的N表示Sorted-Set中成員的數量,M則表示返回的成員數量。該命令的功能和ZRANGE基本相同,唯一的差別在於該命令是通過反向排序獲取指定位置的成員,即從高到低的順序。如果成員具有相同的分數,則按降序字典順序排序。
    • 返回指定的成員列表。
  10. ZREVRANK key member

    • O(log(N)) 時間複雜度中的N表示Sorted-Set中成員的數量。該命令的功能和ZRANK基本相同,唯一的差別在於該命令獲取的索引是從高到低排序後的位置,同樣0表示第一個元素,即分數最高的成員。
    • 如果該成員存在,則返回它的位置索引值。否則返回nil。
  11. ZSCORE key member

    • O(1) 獲取指定Key的指定成員的分數。
    • 如果該成員存在,以字元串的形式返回其分數,否則返回nil。
  12. ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]

    • O(log(N)+M) 時間複雜度中的N表示Sorted-Set中成員的數量,M則表示返回的成員數量。該命令除了排序方式是基於從高到低的分數排序之外,其它功能和參數含義均與ZRANGEBYSCORE相同。
    • 返回分數在指定範圍內的成員列表。
  13. ZREMRANGEBYRANK key start stop

    • O(log(N)+M) 時間複雜度中的N表示Sorted-Set中成員的數量,M則表示被刪除的成員數量。刪除索引位置位於start和stop之間的成員,start和stop都是0-based,即0表示分數最低的成員,-1表示最後一個成員,即分數最高的成員。
    • 被刪除的成員數量。
  14. ZREMRANGEBYSCORE key min max

    • O(log(N)+M) 時間複雜度中的N表示Sorted-Set中成員的數量,M則表示被刪除的成員數量。刪除分數在min和max之間的所有成員,即滿足表達式min <= score <= max的所有成員。對於min和max參數,可以採用開區間的方式表示,具體規則參照ZCOUNT。
    • 被刪除的成員數量。

5.3 命令示例:

  • 1. ZADD/ZCARD/ZCOUNT/ZREM/ZINCRBY/ZSCORE/ZRANGE/ZRANK
##在Shell的命令行下啟動Redis客戶端工具。
/> redis-cli
##添加一個分數為1的成員。
redis 127.0.0.1:6379> zadd myzset 1 "one"
(integer) 1
## 添加兩個分數分別是2和3的兩個成員。
redis 127.0.0.1:6379> zadd myzset 2 "two" 3 "three"
(integer) 2
## 0表示第一個成員,-1表示最後一個成員。
## WITHSCORES選項表示返回的結果中包含每個成員及其分數,否則只返回成員。
redis 127.0.0.1:6379> zrange myzset 0 -1 WITHSCORES
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
## 獲取成員one在Sorted-Set中的位置索引值。0表示第一個位置。
redis 127.0.0.1:6379> zrank myzset one
(integer) 0
## 成員four並不存在,因此返回nil。
redis 127.0.0.1:6379> zrank myzset four
(nil)
## 獲取myzset鍵中成員的數量。    
redis 127.0.0.1:6379> zcard myzset
(integer) 3
## 返回與myzset關聯的Sorted-Set中,
## 分數滿足表達式1 <= score <= 2的成員的數量。
redis 127.0.0.1:6379> zcount myzset 1 2
(integer) 2
## 刪除成員one和two,返回實際刪除成員的數量。
redis 127.0.0.1:6379> zrem myzset one two
(integer) 2
## 查看是否刪除成功。
redis 127.0.0.1:6379> zcard myzset
(integer) 1
#獲取成員three的分數。返回值是字元串形式。
redis 127.0.0.1:6379> zscore myzset three
"3"
## 由於成員two已經被刪除,所以該命令返回nil。
redis 127.0.0.1:6379> zscore myzset two
(nil)
## 將成員one的分數增加2,並返回該成員更新後的分數。
redis 127.0.0.1:6379> zincrby myzset 2 one
"3"
## 將成員one的分數增加-1,並返回該成員更新後的分數。
redis 127.0.0.1:6379> zincrby myzset -1 one
"2"
## 查看在更新了成員的分數後是否正確。
redis 127.0.0.1:6379> zrange myzset 0 -1 WITHSCORES
1) "one"
2) "2"
3) "two"
4) "2"
5) "three"
6) "3"
 
  • 2. ZRANGEBYSCORE/ZREMRANGEBYRANK/ZREMRANGEBYSCORE
redis 127.0.0.1:6379> del myzset
(integer) 1
redis 127.0.0.1:6379> zadd myzset 1 one 2 two 3 three 4 four
(integer) 4
## 獲取分數滿足表達式1 <= score <= 2的成員。
redis 127.0.0.1:6379> zrangebyscore myzset 1 2
1) "one"
2) "two"
## 獲取分數滿足表達式1 < score <= 2的成員。
redis 127.0.0.1:6379> zrangebyscore myzset (1 2
1) "two"
## -inf表示第一個成員,+inf表示最後一個成員,
## limit後面的參數用於限制返回成員的自己,
## 2表示從位置索引(0-based)等於2的成員開始,去後面3個成員。
redis 127.0.0.1:6379> zrangebyscore myzset -inf +inf limit 2 3
1) "three"
2) "four"
## 刪除分數滿足表達式1 <= score <= 2的成員,並返回實際刪除的數量。
redis 127.0.0.1:6379> zremrangebyscore myzset 1 2
(integer) 2
## 看出一下上面的刪除是否成功。
redis 127.0.0.1:6379> zrange myzset 0 -1
1) "three"
2) "four"
## 刪除位置索引滿足表達式0 <= rank <= 1的成員。
redis 127.0.0.1:6379> zremrangebyrank myzset 0 1
(integer) 2
## 查看上一條命令是否刪除成功。
redis 127.0.0.1:6379> zcard myzset
(integer) 0


  • 3. ZREVRANGE/ZREVRANGEBYSCORE/ZREVRANK
## 為後面的示例準備測試數據。
redis 127.0.0.1:6379> del myzset
(integer) 0
redis 127.0.0.1:6379> zadd myzset 1 one 2 two 3 three 4 four
(integer) 4
## 以位置索引從高到低的方式獲取並返回此區間內的成員。
redis 127.0.0.1:6379> zrevrange myzset 0 -1 WITHSCORES
1) "four"
2) "4"
3) "three"
4) "3"
5) "two"
6) "2"
7) "one"
8) "1"
## 由於是從高到低的排序,所以位置等於0的是four,1是three,並以此類推。
redis 127.0.0.1:6379> zrevrange myzset 1 3
1) "three"
2) "two"
3) "one"
## 由於是從高到低的排序,所以one的位置是3。
redis 127.0.0.1:6379> zrevrank myzset one
(integer) 3
## 由於是從高到低的排序,所以four的位置是0。
redis 127.0.0.1:6379> zrevrank myzset four
(integer) 0
## 獲取分數滿足表達式3 >= score >= 0的成員,並以相反的順序輸出,
## 即從高到底的順序。
redis 127.0.0.1:6379> zrevrangebyscore myzset 3 0
1) "three"
2) "two"
3) "one"
## 該命令支持limit選項,其含義等同於zrangebyscore中的該選項,
## 只是在計算位置時按照相反的順序計算和獲取。
redis 127.0.0.1:6379> zrevrangebyscore myzset 4 0 limit 1 2
1) "three"
2) "two"

5.4 應用範圍:

  • 可以用於一個大型線上游戲的積分排行榜。每當玩家的分數發生變化時,可以執行ZADD命令更新玩家的分數,此後再通過ZRANGE命令獲取積分TOPTEN的用戶信息。當然我們也可以利用ZRANK命令通過username來獲取玩家的排行信息。最後我們將組合使用ZRANGE和ZRANK命令快速的獲取和某個玩家積分相近的其他用戶的信息。
  • Sorted-Sets類型還可用於構建索引數據。

六、Key操作

6.1 概述:

  • 此文主要講述的是與Redis數據類型相關的命令,如String、List、Set、Hashes和Sorted-Set。這些命令都具有一個共同點,即所有的操作都是針對與Key關聯的Value的。下麵主要總結了與Key相關的Redis命令。學習這些命令對於學習Redis是非常重要的基礎,也是能夠充分挖掘Redis潛力的利器。
  • 還是按照前面的格式,給出所有相關命令的明細列表和典型示例,以便於現在的學習和今後的查閱。

6.2 相關命令列表:

此後按照如下的排版進行講解:

[命令原型]
* [時間複雜度]   [命令描述]
* 返回值
  1. KEYS pattern

    • O(N) 時間複雜度中的N表示資料庫中Key的數量。獲取所有匹配pattern參數的Keys。需要說明的是,在我們的正常操作中應該儘量避免對該命令的調用,因為對於大型資料庫而言,該命令是非常耗時的,對Redis伺服器的性能打擊也是比較大的。pattern支持glob-style的通配符格式,如*表示任意一個或多個字元,?表示任意字元,[abc]表示方括弧中任意一個字母。
    • 匹配模式的鍵列表。
  2. DEL key [key ...]

    • O(N) 時間複雜度中的N表示刪除的Key數量。從資料庫刪除中參數中指定的keys,如果指定鍵不存在,則直接忽略。還需要另行指出的是,如果指定的Key關聯的數據類型不是String類型,而是List、Set、Hashes和Sorted Set等容器類型,該命令刪除每個鍵的時間複雜度為O(M),其中M表示容器中元素的數量。而對於String類型的Key,其時間複雜度為O(1)。
    • 實際被刪除的Key數量。
  3. EXISTS key

    • O(1) 判斷指定鍵是
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在msdn資源站上看到兩個下載不同的區別,二者都內置專業版,不同之處在於: 具體在哪裡下?百度搜索msdn我告訴你。我還是喜歡使用完全無預裝版本,也就是LTSC版本。 網路上很多LTSB版本很好,LTSC與LTSB都是基於企業版 名詞解釋: LTSB = Long Term Servicing Br ...
  • 自己製作一個簡單的操作系統一[環境搭建] 環境搭建好了? 直接上手 自己製作一個簡單的操作系統二[CherryOS] 一. 軟硬體需求 1. 硬體 一臺電腦, 我使用的是win10(本來想用linux可是沒找到linux版的扇區讀寫工具) 2. 軟體 彙編編譯器:NASM 點擊下載 軟盤絕對扇區讀寫 ...
  • CV:Constant Voltage恆壓 SMMB charger:Switch ModeBattery Charger and Boost peripheral開關模式電池充電器和升壓外圍設備 OCV:Open circuitvoltage EOC:End OfCharge充電結束 UUC:Un ...
  • Rsync 簡介 rsync 是一款開源的、快速的、多功能的、可實現全量及增量的本地或遠程數據同步備份的優秀工具。Rsync軟體適用於unix/linux/windows等多種操作系統平臺。 傳統的 scp 和 cp 工具拷貝每次均為完整拷貝,而rsync除了可以完整拷貝外,還具備增量拷貝功能。因此 ...
  • Linux文件系統原理在所有的操作系統中文件都有文件名與數據,在Linux系統上文件系統分成兩個部分:用戶數據 (user data) 與元數據 (metadata)。用戶數據,即文件數據塊 (data block),數據塊是記錄文件真實內容的地方;而元數據則是文件的附加屬性,如文件大小、創建時間、 ...
  • 對於磁碟等各類存儲設備中所有的數據都以0和1的概念,但對於用戶來說,0和1是沒有任何意義的,這時候就需要一種類似於“翻譯”的機制存在於用戶和磁碟之間,Linux中採用的是文件系統+虛擬文件系統(Virtual File System,VFS)的解決方案 一、文件系統: 就是操作系統用於明確磁碟或分區 ...
  • [TOC] max_connections 允許最大連接數,預設100,最大16384。這個根據性能調節,如果3000連接就會導致mysql的資源不夠,那就給3000.因為再給多了,就會導致其它連接的資源被搶占。 建議: 根據需求來看,一般2核4G機器填寫1000,16核64G填寫5000。 測試運 ...
  • 物理設計:具體任務主要是確定資料庫在存儲設備上的存儲結構及存取方法, 因DBMS的不同還可能包括建立索引和聚集,以及物理塊大小、緩衝區個 數和大小、數據壓縮的選擇等。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...