-
一、String
- 1.1 概述
- 1.2 相關命令串列
- 1.3 命令示例
-
二、List
- 2.1 概述:
- 2.2 相關命令串列:
- 2.3 命令示例:
- 2.4 鏈表結構的小技巧:
-
三、Hashes
- 3.1 概述
- 3.2 相關命令串列
- 3.3 命令示例
-
四、Set
- 4.1 概述:
- 4.2 相關命令串列:
- 4.3 命令示例:
- 4.4 應用范圍:
-
五、Sorted-Sets
- 5.1 概述:
- 5.2 相關命令串列:
- 5.3 命令示例:
- 5.4 應用范圍:
-
六、Key操作
- 6.1 概述:
- 6.2 相關命令串列:
- 6.3 命令示例:
一、String
可以直接看每一大節的命令示例部分,敲一遍就大體會了
1.1 概述
- 字串型別是Redis中最為基礎的資料存盤型別,它在Redis中是二進制安全的,這便意味著該型別可以接受任何格式的資料,如JPEG影像資料或Json物件描述資訊等,在Redis中字串型別的Value最多可以容納的資料長度是512M,
1.2 相關命令串列
此后按照如下的排版進行講解:
[命令原型]
* [時間復雜度] [命令描述]
* 回傳值
- APPEND key value
- O(1) 如果該Key已經存在,APPEND命令將引數Value的資料追加到已存在Value的末尾,如果該Key不存在,APPEND命令將會創建一個新的Key/Value,
- 追加后Value的長度,
- DECR key
- O(1) 將指定Key的Value原子性的遞減1,如果該Key不存在,其初始值為0,在decr之后其值為-1,如果Value的值不能轉換為整型值,如Hello,該操作將執行失敗并回傳相應的錯誤資訊,注意:該操作的取值范圍是64位有符號整型
- 遞減后的Value值,
- INCR key
- O(1) 將指定Key的Value原子性的遞增1,如果該Key不存在,其初始值為0,在incr之后其值為1,如果Value的值不能轉換為整型值,如Hello,該操作將執行失敗并回傳相應的錯誤資訊,注意:該操作的取值范圍是64位有符號整型,
- 遞增后的Value值,
- DECRBY key decrement
- O(1) 將指定Key的Value原子性的減少decrement,如果該Key不存在,其初始值為0,在decrby之后其值為-decrement,如果Value的值不能轉換為整型值,如Hello,該操作將執行失敗并回傳相應的錯誤資訊,注意:該操作的取值范圍是64位有符號整型,
- 減少后的Value值,
- INCRBY key increment
- O(1) 將指定Key的Value原子性的增加increment,如果該Key不存在,其初始值為0,在incrby之后其值為increment,如果Value的值不能轉換為整型值,如Hello,該操作將執行失敗并回傳相應的錯誤資訊,注意:該操作的取值范圍是64位有符號整型,
- 增加后的Value值,
- GET key
- O(1) 獲取指定Key的Value,如果與該Key關聯的Value不是string型別,Redis將回傳錯誤資訊,因為GET命令只能用于獲取string Value,
- 與該Key相關的Value,如果該Key不存在,回傳nil,
- SET key value
- O(1) 設定該Key持有指定的字串Value,如果該Key已經存在,則覆寫其原有值,
- 總是回傳"OK",
- GETSET key value
- O(1) 原子性的設定該Key為指定的Value,同時回傳該Key的原有值,和GET命令一樣,該命令也只能處理string Value,否則Redis將給出相關的錯誤資訊,
- 回傳該Key的原有值,如果該Key之前并不存在,則回傳nil,
- STRLEN key
- O(1) 回傳指定Key的字符值長度,如果Value不是string型別,Redis將執行失敗并給出相關的錯誤資訊,
- 回傳指定Key的Value字符長度,如果該Key不存在,回傳0,
- O(1) 回傳指定Key的字符值長度,如果Value不是string型別,Redis將執行失敗并給出相關的錯誤資訊,
- SETEX key seconds value
- O(1) 原子性完成兩個操作,一是設定該Key的值為指定字串,同時設定該Key在Redis服務器中的存活時間(秒數),該命令主要應用于Redis被當做Cache服務器使用時,
- O(1) 原子性完成兩個操作,一是設定該Key的值為指定字串,同時設定該Key在Redis服務器中的存活時間(秒數),該命令主要應用于Redis被當做Cache服務器使用時,
- SETNX key value
- O(1) 如果指定的Key不存在,則設定該Key持有指定字串Value,此時其效果等價于SET命令,相反,如果該Key已經存在,該命令將不做任何操作并回傳,
- 1表示設定成功,否則0,
- 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長度,
- GETRANGE key start end
- O(1) 如果截取的字串長度很短,我們可以該命令的時間復雜度視為O(1),否則就是O(N),這里N表示截取的子字串長度,該命令在截取子字串時,將以閉區間的方式同時包含start(0表示第一個字符)和end所在的字符,如果end值超過Value的字符長度,該命令將只是截取從start開始之后所有的字符資料,
- 子字串
- 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原有值,
- GETBIT key offset
- O(1) 回傳在指定Offset上BIT的值,0或1,如果Offset超過string value的長度,該命令將回傳0,所以對于空字串始侄訓傳0,
- 在指定Offset上的BIT值,
- MGET key [key ...]
- O(N) N表示獲取Key的數量,回傳所有指定Keys的Values,如果其中某個Key不存在,或者其值不為string型別,該Key的Value將回傳nil,
- 回傳一組指定Keys的Values的串列,
- MSET key value [key value ...]
- O(N) N表示指定Key的數量,該命令原子性的完成引數中所有key/value的設定操作,其具體行為可以看成是多次迭代執行SET命令,
- 該命令不會失敗,始侄訓傳OK,
- MSETNX key value [key value ...]
- O(N) N表示指定Key的數量,該命令原子性的完成引數中所有key/value的設定操作,其具體行為可以看成是多次迭代執行SETNX命令,然而這里需要明確說明的是,如果在這一批Keys中有任意一個Key已經存在了,那么該操作將全部回滾,即所有的修改都不會生效,
- 1表示所有Keys都設定成功,0則表示沒有任何Key被修改,
- O(N) N表示指定Key的數量,該命令原子性的完成引數中所有key/value的設定操作,其具體行為可以看成是多次迭代執行SETNX命令,然而這里需要明確說明的是,如果在這一批Keys中有任意一個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 相關命令串列:
此后按照如下的排版進行講解:
[命令原型]
* [時間復雜度] [命令描述]
* 回傳值
- LPUSH key value [value ...]
- O(1) 在指定Key所關聯的List Value的頭部插入引數中給出的所有Values,如果該Key不存在,該命令將在插入之前創建一個與該Key關聯的空鏈表,之后再將資料從鏈表的頭部插入,如果該鍵的Value不是鏈表型別,該命令將回傳相關的錯誤資訊,
- 插入后鏈表中元素的數量,
- LPUSHX key value
- O(1) 僅有當引數中指定的Key存在時,該命令才會在其所關聯的List Value的頭部插入引數中給出的Value,否則將不會有任何操作發生,
- 插入后鏈表中元素的數量,
- 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)開始,鏈表中剩余的所有元素,
- 回傳指定范圍內元素的串列,
- LPOP key
- O(1) 回傳并彈出指定Key關聯的鏈表中的第一個元素,即頭部元素
- 如果Key不存,回傳nil,
- LLEN key
- O(1) 回傳指定Key關聯的鏈表中元素的數量,如果該Key不存在,則回傳0,如果與該Key關聯的Value的型別不是鏈表,則回傳相關的錯誤資訊,
- 鏈表中元素的數量,
- LREM key count value
- O(N) 時間復雜度中N表示鏈表中元素的數量,在指定Key關聯的鏈表中,洗掉前count個值等于value的元素,如果count大于0,從頭向尾遍歷并洗掉,如果count小于0,則從尾向頭遍歷并洗掉,如果count等于0,則洗掉鏈表中所有等于value的元素,如果指定的Key不存在,則直接回傳0
- 回傳被洗掉的元素數量,
- LSET key index value
- O(N) 時間復雜度中N表示鏈表中元素的數量,但是設定頭部或尾部的元素時,其時間復雜度為O(1),設定鏈表中指定位置的值為新值,其中0表示第一個元素,即頭部元素,-1表示尾部元素,
- 如果索引值Index超出了鏈表中元素的數量范圍,該命令將回傳相關的錯誤資訊,
- LINDEX key index
- O(N) 時間復雜度中N表示在找到該元素時需要遍歷的元素數量,對于頭部或尾部元素,其時間復雜度為O(1),該命令將回傳鏈表中指定位置(index)的元素,index是0-based,表示頭部元素,如果index為-1,表示尾部元素,如果與該Key關聯的不是鏈表,該命令將回傳相關的錯誤資訊,
- 回傳請求的元素,如果index超出范圍,則回傳nil,
- LTRIM key start stop
- O(N) N表示被洗掉的元素數量,該命令將僅保留指定范圍內的元素,從而保證鏈接中的元素數量相對恒定,start和stop引數都是0-based,0表示頭部元素,和其他命令一樣,start和stop也可以為負值,-1表示尾部元素,
- 如果start大于鏈表的尾部,或start大于stop,該命令不錯報錯,而是回傳一個空的鏈表,與此同時該Key也將被洗掉,如果stop大于元素的數量,則保留從start開始剩余的所有元素,
- LINSERT key BEFORE|AFTER pivot value
- O(N) 時間復雜度中N表示在找到該元素pivot之前需要遍歷的元素數量,這樣意味著如果pivot位于鏈表的頭部或尾部時,該命令的時間復雜度為O(1),該命令的功能是在pivot元素的前面或后面插入引數中的元素value,如果Key不存在,該命令將不執行任何操作,如果與Key關聯的Value型別不是鏈表,相關的錯誤資訊將被回傳,
- 成功插入后鏈表中元素的數量,如果沒有找到pivot,回傳-1,如果key不存在,回傳0,
- RPUSH key value [value ...] O
- (1) 在指定Key所關聯的List Value的尾部插入引數中給出的所有Values,如果該Key不存在,該命令將在插入之前創建一個與該Key關聯的空鏈表,之后再將資料從鏈表的尾部插入,如果該鍵的Value不是鏈表型別,該命令將回傳相關的錯誤資訊,
- 插入后鏈表中元素的數量,
- (1) 在指定Key所關聯的List Value的尾部插入引數中給出的所有Values,如果該Key不存在,該命令將在插入之前創建一個與該Key關聯的空鏈表,之后再將資料從鏈表的尾部插入,如果該鍵的Value不是鏈表型別,該命令將回傳相關的錯誤資訊,
- RPUSHX key value
- O(1) 僅有當引數中指定的Key存在時,該命令才會在其所關聯的List Value的尾部插入引數中給出的Value,否則將不會有任何操作發生,
- 插入后鏈表中元素的數量,
- O(1) 僅有當引數中指定的Key存在時,該命令才會在其所關聯的List Value的尾部插入引數中給出的Value,否則將不會有任何操作發生,
- RPOP key
- O(1) 回傳并彈出指定Key關聯的鏈表中的最后一個元素,即尾部元素,,如果該Key不存,回傳nil,
- 鏈表尾部的元素,
- O(1) 回傳并彈出指定Key關聯的鏈表中的最后一個元素,即尾部元素,,如果該Key不存,回傳nil,
- 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 相關命令串列
此后按照如下的排版進行講解:
[命令原型]
* [時間復雜度] [命令描述]
* 回傳值
HSET key field value
- O(1) 為指定的Key設定Field/Value對,如果Key不存在,該命令將創建新Key以引數中的Field/Value對,如果引數中的Field在該Key中已經存在,則用新值覆寫其原有值,
- 1表示新的Field被設定了新值,0表示Field已經存在,用新值覆寫原有值,
HGET key field
- O(1) 回傳指定Key中指定Field的關聯值,
- 回傳引數中Field的關聯值,如果引數中的Key或Field不存,回傳nil,
HEXISTS key field
- O(1) 判斷指定Key中的指定Field是否存在,
- 1表示存在,0表示引數中的Field或Key不存在,
HLEN key
- O(1) 獲取該Key所包含的Field的數量,
- 回傳Key包含的Field數量,如果Key不存在,回傳0,
HDEL key field [field ...] O(N) 時間復雜度中的N表示引數中待洗掉的欄位數量,從指定Key的Hashes Value中洗掉引數中指定的多個欄位,如果不存在的欄位將被忽略,如果Key不存在,則將其視為空Hashes,并回傳0.
- 實際洗掉的Field數量,
HSETNX key field value
- O(1) 只有當引數中的Key或Field不存在的情況下,為指定的Key設定Field/Value對,否則該命令不會進行任何操作,
- 1表示新的Field被設定了新值,0表示Key或Field已經存在,該命令沒有進行任何操作,
HINCRBY key field increment
- O(1) 增加指定Key中指定Field關聯的Value的值,如果Key或Field不存在,該命令將會創建一個新Key或新Field,并將其關聯的Value初始化為0,之后再指定數字增加的操作,該命令支持的數字是64位有符號整型,即increment可以負數,
- 回傳運算后的值,
HGETALL key
- O(N) 時間復雜度中的N表示Key包含的Field數量,獲取該鍵包含的所有Field/Value,其回傳格式為一個Field、一個Value,并以此類推,
- Field/Value的串列,
- O(N) 時間復雜度中的N表示Key包含的Field數量,獲取該鍵包含的所有Field/Value,其回傳格式為一個Field、一個Value,并以此類推,
HKEYS key
- O(N) 時間復雜度中的N表示Key包含的Field數量,回傳指定Key的所有Fields名,
- Field的串列,
HVALS key
- O(N) 時間復雜度中的N表示Key包含的Field數量,回傳指定Key的所有Values名,
- Value的串列,
HMGET key field [field ...]
- O(N) 時間復雜度中的N表示請求的Field數量,獲取和引數中指定Fields關聯的一組Values,
- 如果請求的Field不存在,其值回傳nil,如果Key不存在,該命令將其視為空Hash,因此回傳一組nil, 回傳和請求Fields關聯的一組Values,其回傳順序等同于Fields的請求順序,
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 相關命令串列:
此后按照如下的排版進行講解:
[命令原型]
* [時間復雜度] [命令描述]
* 回傳值
SADD key member [member ...]
- O(N) 時間復雜度中的N表示操作的成員數量,如果在插入的程序用,引數中有的成員在Set中已經存在,該成員將被忽略,而其它成員仍將會被正常插入,如果執行該命令之前,該Key并不存在,該命令將會創建一個新的Set,此后再將引數中的成員陸續插入,如果該Key的Value不是Set型別,該命令將回傳相關的錯誤資訊,
- 本次操作實際插入的成員數量,
SCARD key
- O(1) 獲取Set中成員的數量,
- 回傳Set中成員的數量,如果該Key并不存在,回傳0,
SISMEMBER key member
- O(1) 判斷引數中指定成員是否已經存在于與Key相關聯的Set集合中,
- 1表示已經存在,0表示不存在,或該Key本身并不存在,
SMEMBERS key
- O(N) 時間復雜度中的N表示Set中已經存在的成員數量,獲取與該Key關聯的Set中所有的成員,
- 回傳Set中所有的成員,
SPOP key
- O(1) 隨機的移除并回傳Set中的某一成員, 由于Set中元素的布局不受外部控制,因此無法像List那樣確定哪個元素位于Set的頭部或者尾部,
- 回傳移除的成員,如果該Key并不存在,則回傳nil,
SREM key member [member ...]
- O(N) 時間復雜度中的N表示被洗掉的成員數量,從與Key關聯的Set中洗掉引數中指定的成員,不存在的引數成員將被忽略,如果該Key并不存在,將視為空Set處理,
- 從Set中實際移除的成員數量,如果沒有則回傳0,
SRANDMEMBER key
- O(1) 和SPOP一樣,隨機的回傳Set中的一個成員,不同的是該命令并不會洗掉回傳的成員,
- 回傳隨機位置的成員,如果Key不存在則回傳nil,
SMOVE source destination member
- O(1) 原子性的將引數中的成員從source鍵移入到destination鍵所關聯的Set中,因此在某一時刻,該成員或者出現在source中,或者出現在destination中,如果該成員在source中并不存在,該命令將不會再執行任何操作并回傳0,否則,該成員將從source移入到destination,如果此時該成員已經在destination中存在,那么該命令僅是將該成員從source中移出,如果和Key關聯的Value不是Set,將回傳相關的錯誤資訊,
- 1表示正常移動,0表示source中并不包含引數成員,
SDIFF key [key ...]
- O(N) 時間復雜度中的N表示所有Sets中成員的總數量,回傳引數中第一個Key所關聯的Set和其后所有Keys所關聯的Sets中成員的差異,如果Key不存在,則視為空Set,
- 差異結果成員的集合,
SDIFFSTORE destination key [key ...]
- O(N) 該命令和SDIFF命令在功能上完全相同,兩者之間唯一的差別是SDIFF回傳差異的結果成員,而該命令將差異成員存盤在destination關聯的Set中,如果destination鍵已經存在,該操作將覆寫它的成員,
- 回傳差異成員的數量,
SINTER key [key ...]
- O(N*M) 時間復雜度中的N表示最小Set中元素的數量,M則表示引數中Sets的數量,該命令將回傳引數中所有Keys關聯的Sets中成員的交集,因此如果引數中任何一個Key關聯的Set為空,或某一Key不存在,那么該命令的結果將為空集,
- 交集結果成員的集合,
SINTERSTORE destination key [key ...]
- O(N*M) 該命令和SINTER命令在功能上完全相同,兩者之間唯一的差別是SINTER回傳交集的結果成員,而該命令將交集成員存盤在destination關聯的Set中,如果destination鍵已經存在,該操作將覆寫它的成員,
- 回傳交集成員的數量,
SUNION key [key ...]
- O(N) 時間復雜度中的N表示所有Sets中成員的總數量,該命令將回傳引數中所有Keys關聯的Sets中成員的并集, 并集結果成員的集合,
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 相關命令串列:
此后按照如下的排版進行講解:
[命令原型]
* [時間復雜度] [命令描述]
* 回傳值
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型別,相關的錯誤資訊將被回傳,
- 本次操作實際插入的成員數量,
ZCARD key
- O(1) 獲取與該Key相關聯的Sorted-Sets中包含的成員數量,
- 回傳Sorted-Sets中的成員數量,如果該Key不存在,回傳0,
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,
- 分數指定范圍內成員的數量,
- 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,
ZINCRBY key increment member
- O(log(N)) 該命令將為指定Key中的指定成員增加指定的分數,如果成員不存在,該命令將添加該成員并假設其初始分數為0,此后再將其分數加上increment,如果Key不存,該命令將創建該Key及其關聯的Sorted-Sets,并包含引數指定的成員,其分數為increment引數,如果與該Key關聯的不是Sorted-Sets型別,相關的錯誤資訊將被回傳,
- 以字串形式表示的新分數,
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之間的成員串列,
- 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...,
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,
- 回傳分數在指定范圍內的成員串列,
ZRANK key member
- O(log(N)) 時間復雜度中的N表示Sorted-Set中成員的數量,Sorted-Set中的成員都是按照分數從低到高的順序存盤,該命令將回傳引數中指定成員的位置值,其中0表示第一個成員,它是Sorted-Set中分數最低的成員,
- 如果該成員存在,則回傳它的位置索引值,否則回傳nil,
ZREM key member [member ...]
- O(M log(N)) 時間復雜度中N表示Sorted-Set中成員的數量,M則表示被洗掉的成員數量,該命令將移除引數中指定的成員,其中不存在的成員將被忽略,如果與該Key關聯的Value不是Sorted-Set,相應的錯誤資訊將被回傳,
- 實際被洗掉的成員數量,
ZREVRANGE key start stop [WITHSCORES]
- O(log(N)+M) 時間復雜度中的N表示Sorted-Set中成員的數量,M則表示回傳的成員數量,該命令的功能和ZRANGE基本相同,唯一的差別在于該命令是通過反向排序獲取指定位置的成員,即從高到低的順序,如果成員具有相同的分數,則按降序字典順序排序,
- 回傳指定的成員串列,
- O(log(N)+M) 時間復雜度中的N表示Sorted-Set中成員的數量,M則表示回傳的成員數量,該命令的功能和ZRANGE基本相同,唯一的差別在于該命令是通過反向排序獲取指定位置的成員,即從高到低的順序,如果成員具有相同的分數,則按降序字典順序排序,
ZREVRANK key member
- O(log(N)) 時間復雜度中的N表示Sorted-Set中成員的數量,該命令的功能和ZRANK基本相同,唯一的差別在于該命令獲取的索引是從高到低排序后的位置,同樣0表示第一個元素,即分數最高的成員,
- 如果該成員存在,則回傳它的位置索引值,否則回傳nil,
ZSCORE key member
- O(1) 獲取指定Key的指定成員的分數,
- 如果該成員存在,以字串的形式回傳其分數,否則回傳nil,
ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]
- O(log(N)+M) 時間復雜度中的N表示Sorted-Set中成員的數量,M則表示回傳的成員數量,該命令除了排序方式是基于從高到低的分數排序之外,其它功能和引數含義均與ZRANGEBYSCORE相同,
- 回傳分數在指定范圍內的成員串列,
ZREMRANGEBYRANK key start stop
- O(log(N)+M) 時間復雜度中的N表示Sorted-Set中成員的數量,M則表示被洗掉的成員數量,洗掉索引位置位于start和stop之間的成員,start和stop都是0-based,即0表示分數最低的成員,-1表示最后一個成員,即分數最高的成員,
- 被洗掉的成員數量,
- O(log(N)+M) 時間復雜度中的N表示Sorted-Set中成員的數量,M則表示被洗掉的成員數量,洗掉索引位置位于start和stop之間的成員,start和stop都是0-based,即0表示分數最低的成員,-1表示最后一個成員,即分數最高的成員,
ZREMRANGEBYSCORE key min max
- O(log(N)+M) 時間復雜度中的N表示Sorted-Set中成員的數量,M則表示被洗掉的成員數量,洗掉分數在min和max之間的所有成員,即滿足運算式min <= score <= max的所有成員,對于min和max引數,可以采用開區間的方式表示,具體規則參照ZCOUNT,
- 被洗掉的成員數量,
- 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 相關命令串列:
此后按照如下的排版進行講解:
[命令原型]
* [時間復雜度] [命令描述]
* 回傳值
KEYS pattern
- O(N) 時間復雜度中的N表示資料庫中Key的數量,獲取所有匹配pattern引數的Keys,需要說明的是,在我們的正常操作中應該盡量避免對該命令的呼叫,因為對于大型資料庫而言,該命令是非常耗時的,對Redis服務器的性能打擊也是比較大的,pattern支持glob-style的通配符格式,如*表示任意一個或多個字符,?表示任意字符,[abc]表示方括號中任意一個字母,
- 匹配模式的鍵串列,
DEL key [key ...]
- O(N) 時間復雜度中的N表示洗掉的Key數量,從資料庫洗掉中引數中指定的keys,如果指定鍵不存在,則直接忽略,還需要另行指出的是,如果指定的Key關聯的資料型別不是String型別,而是List、Set、Hashes和Sorted Set等容器型別,該命令洗掉每個鍵的時間復雜度為O(M),其中M表示容器中元素的數量,而對于String型別的Key,其時間復雜度為O(1),
- 實際被洗掉的Key數量,
EXISTS key
- O(1) 判斷指定鍵是否存在
- 1表示存在,0表示不存在,
MOVE key db
- O(1) 將當前資料庫中指定的鍵Key移動到引數中指定的資料庫中,如果該Key在目標資料庫中已經存在,或者在當前資料庫中并不存在,該命令將不做任何操作并回傳0,
- 移動成功回傳1,否則0,
- O(1) 將當前資料庫中指定的鍵Key移動到引數中指定的資料庫中,如果該Key在目標資料庫中已經存在,或者在當前資料庫中并不存在,該命令將不做任何操作并回傳0,
RENAME key newkey
- O(1) 為指定指定的鍵重新命名,如果引數中的兩個Keys的命令相同,或者是源Key不存在,該命令都會回傳相關的錯誤資訊,如果newKey已經存在,則直接覆寫,
- O(1) 為指定指定的鍵重新命名,如果引數中的兩個Keys的命令相同,或者是源Key不存在,該命令都會回傳相關的錯誤資訊,如果newKey已經存在,則直接覆寫,
RENAMENX key newkey
- O(1) 如果新值不存在,則將引數中的原值修改為新值,其它條件和RENAME一致,
- 1表示修改成功,否則0,
PERSIST key
- O(1) 如果Key存在過期時間,該命令會將其過期時間消除,使該Key不再有超時,而是可以持久化存盤,
- 1表示Key的過期時間被移出,0表示該Key不存在或沒有過期時間,
EXPIRE key seconds
- O(1) 該命令為引數中指定的Key設定超時的秒數,在超過該時間后,Key被自動的洗掉,如果該Key在超時之前被修改,與該鍵關聯的超時將被移除,
- 1表示超時被設定,0則表示Key不存在,或不能被設定,
EXPIREAT key timestamp
- O(1) 該命令的邏輯功能和EXPIRE完全相同,唯一的差別是該命令指定的超時時間是絕對時間,而不是相對時間,該時間引數是Unix timestamp格式的,即從1970年1月1日開始所流經的秒數
- 1表示超時被設定,0則表示Key不存在,或不能被設定,
TTL key
- O(1) 獲取該鍵所剩的超時描述,
- 回傳所剩描述,如果該鍵不存在或沒有超時設定,則回傳-1,
RANDOMKEY
- O(1) 從當前打開的資料庫中隨機的回傳一個Key,
- 回傳的隨機鍵,如果該資料庫是空的則回傳nil,
TYPE key
- O(1) 獲取與引數中指定鍵關聯值的型別,該命令將以字串的格式回傳,
- 回傳的字串為string、list、set、hash和zset,如果key不存在回傳none,
SORT key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern ...]] [ASC|DESC] [ALPHA] [STORE destination]
- O(N+M*log(M)) 這個命令相對來說是比較復雜的,因此我們這里只是給出最基本的用法,有興趣的網友可以去參考redis的官方檔案,
- 回傳排序后的原始串列,
6.3 命令示例:
- 1. KEYS/RENAME/DEL/EXISTS/MOVE/RENAMENX
## 在Shell命令列下啟動Redis客戶端工具,
/> redis-cli
## 清空當前選擇的資料庫,以便于對后面示例的理解,
redis 127.0.0.1:6379> flushdb
OK
## 添加String型別的模擬資料,
redis 127.0.0.1:6379> set mykey 2
OK
redis 127.0.0.1:6379> set mykey2 "hello"
OK
## 添加Set型別的模擬資料,
redis 127.0.0.1:6379> sadd mysetkey 1 2 3
(integer) 3
## 添加Hash型別的模擬資料,
redis 127.0.0.1:6379> hset mmtest username "study"
(integer) 1
## 根據引數中的模式,獲取當前資料庫中符合該模式的所有key,
## 從輸出可以看出,該命令在執行時并不區分與Key關聯的Value型別,
redis 127.0.0.1:6379> keys my*
1) "mysetkey"
2) "mykey"
3) "mykey2"
## 洗掉了兩個Keys,
redis 127.0.0.1:6379> del mykey mykey2
(integer) 2
## 查看一下剛剛洗掉的Key是否還存在,從回傳結果看,mykey確實已經洗掉了,
redis 127.0.0.1:6379> exists mykey
(integer) 0
## 查看一下沒有洗掉的Key,以和上面的命令結果進行比較,
redis 127.0.0.1:6379> exists mysetkey
(integer) 1
## 將當前資料庫中的mysetkey鍵移入到ID為1的資料庫中,
## 從結果可以看出已經移動成功,
redis 127.0.0.1:6379> move mysetkey 1
(integer) 1
## 打開ID為1的資料庫,
redis 127.0.0.1:6379> select 1
OK
## 查看一下剛剛移動過來的Key是否存在,從回傳結果看已經存在了,
redis 127.0.0.1:6379[1]> exists mysetkey
(integer) 1
## 在重新打開ID為0的預設資料庫,
redis 127.0.0.1:6379[1]> select 0
OK
## 查看一下剛剛移走的Key是否已經不存在,從回傳結果看已經移走,
redis 127.0.0.1:6379> exists mysetkey
(integer) 0
## 準備新的測驗資料,
redis 127.0.0.1:6379> set mykey "hello"
OK
## 將mykey改名為mykey1
redis 127.0.0.1:6379> rename mykey mykey1
OK
## 由于mykey已經被重新命名,再次獲取將回傳nil,
redis 127.0.0.1:6379> get mykey
(nil)
## 通過新的鍵名獲取,
redis 127.0.0.1:6379> get mykey1
"hello"
## 由于mykey已經不存在了,所以回傳錯誤資訊,
redis 127.0.0.1:6379> rename mykey mykey1
(error) ERR no such key
## 為renamenx準備測驗key
redis 127.0.0.1:6379> set oldkey "hello"
OK
redis 127.0.0.1:6379> set newkey "world"
OK
## 由于newkey已經存在,因此該命令未能成功執行,
redis 127.0.0.1:6379> renamenx oldkey newkey
(integer) 0
## 查看newkey的值,發現它也沒有被renamenx覆寫,
redis 127.0.0.1:6379> get newkey
"world"
- 2. PERSIST/EXPIRE/EXPIREAT/TTL
## 為后面的示例準備的測驗資料,
redis 127.0.0.1:6379> set mykey "hello"
OK
## 將該鍵的超時設定為100秒,
redis 127.0.0.1:6379> expire mykey 100
(integer) 1
## 通過ttl命令查看一下還剩下多少秒,
redis 127.0.0.1:6379> ttl mykey
(integer) 97
## 立刻執行persist命令,該存在超時的鍵變成持久化的鍵,即將該Key的超時去掉,
redis 127.0.0.1:6379> persist mykey
(integer) 1
## ttl的回傳值告訴我們,該鍵已經沒有超時了,
redis 127.0.0.1:6379> ttl mykey
(integer) -1
## 為后面的expire命令準備資料,
redis 127.0.0.1:6379> del mykey
(integer) 1
redis 127.0.0.1:6379> set mykey "hello"
OK
## 設定該鍵的超時被100秒,
redis 127.0.0.1:6379> expire mykey 100
(integer) 1
## 用ttl命令看一下當前還剩下多少秒,從結果中可以看出還剩下96秒,
redis 127.0.0.1:6379> ttl mykey
(integer) 96
## 重新更新該鍵的超時時間為20秒,從回傳值可以看出該命令執行成功,
redis 127.0.0.1:6379> expire mykey 20
(integer) 1
## 再用ttl確認一下,從結果中可以看出果然被更新了,
redis 127.0.0.1:6379> ttl mykey
(integer) 17
## 立刻更新該鍵的值,以使其超時無效,
redis 127.0.0.1:6379> set mykey "world"
OK
## 從ttl的結果可以看出,在上一條修改該鍵的命令執行后,該鍵的超時也無效了,
redis 127.0.0.1:6379> ttl mykey
(integer) -1
- 3. TYPE/RANDOMKEY/SORT
## 由于mm鍵在資料庫中不存在,因此該命令回傳none,
redis 127.0.0.1:6379> type mm
none
## mykey的值是字串型別,因此回傳string,
redis 127.0.0.1:6379> type mykey
string
## 準備一個值是set型別的鍵,
redis 127.0.0.1:6379> sadd mysetkey 1 2
(integer) 2
## mysetkey的鍵是set,因此回傳字串set,
redis 127.0.0.1:6379> type mysetkey
set
## 回傳資料庫中的任意鍵,
redis 127.0.0.1:6379> randomkey
"oldkey"
## 清空當前打開的資料庫,
redis 127.0.0.1:6379> flushdb
OK
## 由于沒有資料了,因此回傳nil,
redis 127.0.0.1:6379> randomkey
(nil)
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/40068.html
標籤:NoSQL
上一篇:redis3集群管理
下一篇:Redis 的主從同步(復制)
