自1.0.0起可用。時間複雜度: O(N),
N
爲數據庫中key
的數量。web
查找全部符合給定模式 pattern
的 key
。redis
KEYS *
匹配數據庫中全部 key
。算法
KEYS h?llo
匹配 hello
, hallo
和 hxllo
等。shell
KEYS h*llo
匹配 hllo
和 heeeeello
等。數據庫
KEYS h[ae]llo
匹配 hello
和 hallo
,但不匹配 hillo
。數組
特殊符號用 \
隔開安全
KEYS
的速度很是快,但在一個大的數據庫中使用它仍然可能形成性能問題,若是你須要從一個數據集中查找特定的 key
,你最好仍是用 Redis 的集合結構 (set)來代替。服務器
符合給定模式的 key
列表。網絡
coderknock> KEYS * 1) "name:45" 2) "like_blog_num" 3) "user:3" 4) "40Key" 5) "test" 6) "coderknockCounter" 7) "user:45" 8) "str" 9) "strHash" 10) "39Key" 11) "testChinese" 12) "user:5" 13) "intKey" 14) "embstrKey" 15) "map" 16) "user:34" coderknock> KEYS user:* 1) "user:3" 2) "user:45" 3) "user:5" 4) "user:34" coderknock> KEYS [34][09]Key 1) "40Key" 2) "39Key" coderknock> KEYS user:[3]? 1) "user:34" coderknock> KEYS user:[35] 1) "user:3" 2) "user:5" coderknock> KEYS user:[3]* 1) "user:3" 2) "user:34" coderknock> KEYS *Key 1) "40Key" 2) "39Key" 3) "intKey" 4) "embstrKey"
自1.0.0起可用。時間複雜度: O(1)。數據結構
返回當前數據庫的 key
的數量。
當前數據庫的 key
的數量。
coderknock> DBSIZE (integer) 16 coderknock> DBSIZE (integer) 16 coderknock> DBSIZE (integer) 16 # 添加一個 key coderknock> SET addKey name coderknock> DBSIZE (integer) 17
DBSIZE
命令在計算鍵總數時不會遍歷全部鍵,而是直接獲取 Redis 內置的鍵總數變量,因此 DBSIZE
命令的時間複雜度是 O(1)。而 KEYS
命令會遍歷全部鍵,因此它的時間複雜度是 O(n),當 Redis 保存了大量鍵時,線上環境最好禁止使用 KEYS
。
自1.0.0起可用。時間複雜度: O(1)。
key
檢查給定 key
是否存在。
若 key
存在,返回存在的 key
的個數,不然返回 0
。
coderknock> EXISTS addKey (integer) 1 coderknock> EXISTS a (integer) 0 # 同時查詢多個 coderknock> EXISTS addKey user:3 user:5 a embstrKey (integer) 4
自1.0.0起可用。時間複雜度: O(N),
N
爲被刪除的key
的數量。刪除單個字符串類型的
key
,時間複雜度爲O(1)。刪除單個列表、集合、有序集合或哈希表類型的
key
,時間複雜度爲O(M),M
爲以上數據結構內的元素數量。
刪除給定的一個或多個 key
。
不存在的 key
會被忽略。
DEL 是一個通用命令,不管值是什麼數據結構類型,DEL 命令均可以將其刪除
被刪除 key
的數量。
coderknock> HGETALL user:5 1) "name" 2) "coverSanchan" 3) "website" 4) "https://www.coderknock.com" 5) "user" 6) "sanchan" coderknock> DEL user:5 (integer) 1 coderknock> DEL user:5 (integer) 0
自1.0.0起可用。時間複雜度: O(1)
爲給定 key
設置生存時間,當 key
過時時(生存時間爲 0
),它會被自動刪除。
在 Redis 中,帶有生存時間的 key
被稱爲『易失的』(volatile)。
生存時間能夠經過使用 DEL
命令來刪除整個 key
來移除,或者被 SET
和 GETSET
命令覆寫(overwrite),這意味着,若是一個命令只是修改(alter)一個帶生存時間的 key
的值而不是用一個新的 key
值來代替(replace)它的話,那麼生存時間不會被改變。
好比說,對一個 key
執行 INCR
命令,對一個列表進行 LPUSH
命令,或者對一個哈希表執行 HSET
命令,這類操做都不會修改 key
自己的生存時間。
另外一方面,若是使用 RENAME
對一個 key
進行更名,那麼更名後的 key
的生存時間和更名前同樣。
RENAME
命令的另外一種多是,嘗試將一個帶生存時間的 key
更名成另外一個帶生存時間的 another_key
,這時舊的 another_key
(以及它的生存時間)會被刪除,而後舊的 key
會更名爲 another_key
,所以,新的 another_key
的生存時間也和本來的 key
同樣。
使用 PERSIST
命令能夠在不刪除 key
的狀況下,移除 key
的生存時間,讓 key
從新成爲一個『持久的』(persistent) key
。
更新生存時間
能夠對一個已經帶有生存時間的 key
執行 EXPIRE
命令,新指定的生存時間會取代舊的生存時間。
過時時間的精確度
在 Redis 2.4 版本中,過時時間的延遲在 1 秒鐘以內 —— 也便是,就算 key
已通過期,但它仍是可能在過時以後一秒鐘以內被訪問到,而在新的 Redis 2.6 版本中,延遲被下降到 1 毫秒以內。
Redis 2.1.3 以前的不一樣之處
在 Redis 2.1.3 以前的版本中,修改一個帶有生存時間的 key
會致使整個 key
被刪除,這一行爲是受當時複製(replication)層的限制而做出的,如今這一限制已經被修復。
設置成功返回 1
。
當 key
不存在或者不能爲 key
設置生存時間時(好比在低於 2.1.3 版本的 Redis 中你嘗試更新 key
的生存時間),返回 0
。
redis> SET cache_website "www.coderknock.com" OK redis> EXPIRE cache_website 30 # 設置過時時間爲 30 秒 (integer) 1 redis> TTL cache_website # 查看剩餘生存時間 (integer) 23 redis> EXPIRE cache_website 30000 # 更新過時時間 (integer) 1 redis> TTL cache_website (integer) 29996 # 在 SET 命令中也能夠直接 設置過時時間【SET 命令在 《Redis 字符串》中會講解】 coderknock> SET cache_website "www.coderknock.com" EX 30 OK coderknock> TTL cache_website (integer) 13 # 30 秒後該鍵被刪除 coderknock> EXISTS cache_website (integer) 0
自1.0.0起可用。時間複雜度: O(1)
以秒爲單位,返回給定 key
的剩餘生存時間(TTL, time to live)。
當 key
不存在時,返回 -2
。
當 key
存在但沒有設置剩餘生存時間時,返回 -1
。
不然,以秒爲單位,返回 key
的剩餘生存時間。
在 Redis 2.8 之前,當 key
不存在,或者 key
沒有設置剩餘生存時間時,命令都返回 -1
。
#TTL 正常使用在上面一個命令中已經有示例,下面演示一個對不存在 key 使用的狀況以及對沒有設置過時時間可使用的狀況 # 不存在 key coderknock> TTL cache_website (integer) -2 # 存在可是未設置過時時間的 key coderknock> TTL user:3 (integer) -1
TYPE
自1.0.0起可用。時間複雜度: O(1)
返回 key
所儲存的值的類型。
none
(key不存在)
string
(字符串)
list
(列表)
set
(集合)
zset
(有序集)
hash
(哈希表)
# 哈希 coderknock> TYPE user:3 hash # 不存在 coderknock> TYPE a none # 字符串 coderknock> TYPE embstrKey string
SCAN
自2.8.0起可用。時間複雜度: 增量式迭代命令每次執行的複雜度爲 O(1) , 對數據集進行一次完整迭代的複雜度爲 O(N), 其中
N
爲數據集中的元素數量。
SCAN
命令及其相關的 SSCAN
命令、 HSCAN
命令和 ZSCAN
命令都用於增量地迭代(incrementally iterate)一集元素(a collection of elements):
SCAN
命令用於迭代當前數據庫中的數據庫鍵。SSCAN
命令用於迭代集合鍵中的元素。HSCAN
命令用於迭代哈希鍵中的鍵值對。ZSCAN
命令用於迭代有序集合中的元素(包括元素成員和元素分值)。以上列出的四個命令都支持增量式迭代, 它們每次執行都只會返回少許元素, 因此這些命令能夠用於生產環境, 而不會出現像 KEYS
命令、 SMEMBERS
命令帶來的問題 —— 當 KEYS
命令被用於處理一個大的數據庫時, 又或者 SMEMBERS
命令被用於處理一個大的集合鍵時, 它們可能會阻塞服務器達數秒之久。
不過, 增量式迭代命令也不是沒有缺點的: 舉個例子, 使用 SMEMBERS
命令能夠返回集合鍵當前包含的全部元素, 可是對於 SCAN
這類增量式迭代命令來講, 由於在對鍵進行增量式迭代的過程當中, 鍵可能會被修改, 因此增量式迭代命令只能對被返回的元素提供有限的保證 (offer limited guarantees about the returned elements)。
由於 SCAN
、 SSCAN
、 HSCAN
和 ZSCAN
四個命令的工做方式都很是類似, 因此這個文檔會一併介紹這四個命令, 可是要記住:
SSCAN
命令、 HSCAN
命令和 ZSCAN
命令的第一個參數老是一個數據庫鍵。SCAN
命令則不須要在第一個參數提供任何數據庫鍵 —— 由於它迭代的是當前數據庫中的全部數據庫鍵。SCAN
命令是一個基於遊標的迭代器(cursor based iterator): SCAN
命令每次被調用以後, 都會向用戶返回一個新的遊標, 用戶在下次迭代時須要使用這個新遊標做爲 SCAN
命令的遊標參數, 以此來延續以前的迭代過程。
當 SCAN
命令的遊標參數被設置爲 0
時, 服務器將開始一次新的迭代, 而當服務器向用戶返回值爲 0
的遊標時, 表示迭代已結束。
SCAN
命令的迭代過程示例:coderknock> SCAN 0 1) "13" # 這個爲下一個 SCAN 使用的 cursor 2) 1) "name:45" 2) "coderknockCounter" 3) "intKey" 4) "addKey" 5) "like_blog_num" 6) "map" 7) "str" 8) "user:45" 9) "40Key" 10) "user:3" coderknock> SCAN 13 1) "0" 2) 1) "embstrKey" 2) "testChinese" 3) "strHash" 4) "39Key" 5) "test" 6) "user:34"
在上面這個例子中, 第一次迭代使用 0
做爲遊標, 表示開始一次新的迭代。
第二次迭代使用的是第一次迭代時返回的遊標, 也便是命令回覆第一個元素的值 —— 13
。
從上面的示例能夠看到, SCAN
命令的回覆是一個包含兩個元素的數組, 第一個數組元素是用於進行下一次迭代的新遊標, 而第二個數組元素則是一個數組, 這個數組中包含了全部被迭代的元素。
在第二次調用 SCAN
命令時, 命令返回了遊標 0
, 這表示迭代已經結束, 整個數據集(collection)已經被完整遍歷過了。
以 0
做爲遊標開始一次新的迭代, 一直調用 SCAN
命令, 直到命令返回遊標 0
, 咱們稱這個過程爲一次完整遍歷(full iteration)。
SCAN
命令, 以及其餘增量式迭代命令, 在進行完整遍歷的狀況下能夠爲用戶帶來如下保證: 從完整遍歷開始直到完整遍歷結束期間, 一直存在於數據集內的全部元素都會被完整遍歷返回; 這意味着, 若是有一個元素, 它從遍歷開始直到遍歷結束期間都存在於被遍歷的數據集當中, 那麼 SCAN
命令總會在某次迭代中將這個元素返回給用戶。
然而由於增量式命令僅僅使用遊標來記錄迭代狀態, 因此這些命令帶有如下缺點:
增量式迭代命令並不保證每次執行都返回某個給定數量的元素。
增量式命令甚至可能會返回零個元素, 但只要命令返回的遊標不是 0
, 應用程序就不該該將迭代視做結束。
不過命令返回的元素數量老是符合必定規則的, 在實際中:
最後, 用戶能夠經過增量式迭代命令提供的 COUNT
選項來指定每次迭代返回元素的最大值。
雖然增量式迭代命令不保證每次迭代所返回的元素數量, 但咱們可使用 COUNT
選項, 對命令的行爲進行必定程度上的調整。
基本上, COUNT
選項的做用就是讓用戶告知迭代命令, 在每次迭代中應該從數據集裏返回多少元素。
雖然 COUNT
選項只是對增量式迭代命令的一種提示(hint), 可是在大多數狀況下, 這種提示都是有效的。
COUNT
參數的默認值爲 10
。MATCH
選項, 那麼命令返回的元素數量一般和 COUNT
選項指定的同樣, 或者比 COUNT
選項指定的數量稍多一些。COUNT
選項指定的值, 在第一次迭代就將數據集包含的全部元素都返回給用戶。並不是每次迭代都要使用相同的 COUNT
值。
用戶能夠在每次迭代中按本身的須要隨意改變 COUNT
值, 只要記得將上次迭代返回的遊標用到下次迭代裏面就能夠了。
coderknock> SCAN 0 COUNT 20 1) "0" 2) 1) "name:45" 2) "coderknockCounter" 3) "intKey" 4) "addKey" 5) "like_blog_num" 6) "map" 7) "str" 8) "user:45" 9) "40Key" 10) "user:3" 11) "embstrKey" 12) "testChinese" 13) "strHash" 14) "39Key" 15) "test" 16) "user:34" coderknock> SCAN 0 COUNT 5 1) "10" 2) 1) "name:45" 2) "coderknockCounter" 3) "intKey" 4) "addKey" 5) "like_blog_num" coderknock> SCAN 10 1) "15" 2) 1) "map" 2) "str" 3) "user:45" 4) "40Key" 5) "user:3" 6) "embstrKey" 7) "testChinese" 8) "strHash" 9) "39Key" 10) "test" coderknock> SCAN 15 1) "0" 2) 1) "user:34"
和 KEYS
命令同樣, 增量式迭代命令也能夠經過提供一個 glob 風格的模式參數, 讓命令只返回和給定模式相匹配的元素, 這一點能夠經過在執行增量式迭代命令時, 經過給定 MATCH <pattern>
參數來實現。
如下是一個使用 MATCH
選項進行迭代的示例:
coderknock> SADD test 1 2 3 4 11 12 13 14 a ab abc abcd (integer) 12 coderknock> SSCAN test 0 MATCH ab* 1) "3" 2) 1) "abcd" 2) "abc" coderknock> SSCAN test 3 MATCH ab* 1) "0" 2) 1) "ab" # 下面的語句說明要注意 調用 cursor 時 可選項一致,否則獲取的數據沒有意義 coderknock> SSCAN test 3 1) "0" 2) 1) "ab" 2) "12" coderknock>
須要注意的是, 對元素的模式匹配工做是在命令從數據集中取出元素以後, 向客戶端返回元素以前的這段時間內進行的, 因此若是被迭代的數據集中只有少許元素和模式相匹配, 那麼迭代命令或許會在屢次執行中都不返回任何元素。
如下是這種狀況的一個例子:
coderknock> keys * 1) "name:45" 2) "addKey" 3) "40Key" 4) "coderknockCounter" 5) "testChinese" 6) "strHash" 7) "embstrKey" 8) "map" 9) "like_blog_num" 10) "user:3" 11) "test" 12) "str" 13) "user:45" 14) "39Key" 15) "intKey" 16) "user:34" # 可選項的關鍵字不能輸入錯誤,不然會報錯 coderknock> SCAN 0 MACH em (error) ERR syntax error coderknock> SCAN 0 MATCH em 1) "13" 2) (empty list or set) coderknock> SCAN 13 MATCH 5 1) "0" 2) (empty list or set)
如你所見, 以上的大部分迭代都不返回任何元素。
在同一時間, 能夠有任意多個客戶端對同一數據集進行迭代, 客戶端每次執行迭代都須要傳入一個遊標, 並在迭代執行以後得到一個新的遊標, 而這個遊標就包含了迭代的全部狀態, 所以, 服務器無須爲迭代記錄任何狀態。
由於迭代的全部狀態都保存在遊標裏面, 而服務器無須爲迭代保存任何狀態, 因此客戶端能夠在中途中止一個迭代, 而無須對服務器進行任何通知。
即便有任意數量的迭代在中途中止, 也不會產生任何問題。
使用間斷的(broken)、負數、超出範圍或者其餘非正常的遊標來執行增量式迭代並不會形成服務器崩潰, 但可能會讓命令產生未定義的行爲。
未定義行爲指的是, 增量式命令對返回值所作的保證可能會再也不爲真。
只有兩種遊標是合法的:
0
。增量式迭代命令所使用的算法只保證在數據集的大小有界(bounded)的狀況下, 迭代纔會中止, 換句話說, 若是被迭代數據集的大小不斷地增加的話, 增量式迭代命令可能永遠也沒法完成一次完整迭代。
從直覺上能夠看出, 當一個數據集不斷地變大時, 想要訪問這個數據集中的全部元素就須要作愈來愈多的工做, 可否結束一個迭代取決於用戶執行迭代的速度是否比數據集增加的速度更快。
返回值:
SCAN
命令、SSCAN
命令、HSCAN
命令和ZSCAN
命令都返回一個包含兩個元素的 multi-bulk 回覆: 回覆的第一個元素是字符串表示的無符號 64 位整數(遊標), 回覆的第二個元素是另外一個 multi-bulk 回覆, 這個 multi-bulk 回覆包含了本次被迭代的元素。
SCAN
命令返回的每一個元素都是一個數據庫鍵。
SSCAN
命令返回的每一個元素都是一個集合成員。
HSCAN
命令返回的每一個元素都是一個鍵值對,一個鍵值對由一個鍵和一個值組成。
ZSCAN
命令返回的每一個元素都是一個有序集合元素,一個有序集合元素由一個成員(member)和一個分值(score)組成。
字符串是一種最基本的Redis值類型。key
都是字符串類型,其餘幾種數據結構都是在字符串類型的基礎上構建的。Redis字符串是二進制安全的,這意味着一個Redis字符串能包含任意類型的數據,例如: 一張JPEG格式的圖片或者一個序列化的 Ruby 對象等。
一個字符串類型的值最多能存儲 512M 字節的內容。
字符串類型的值實際上能夠如下幾種:
你能夠用Redis字符串作許多有趣的事,例如你能夠:
INCR
命令簇(INCR
DECR
INCRBY
)來把字符串看成原子計數器使用。APPEND
命令在字符串後添加內容。GETRANGE
和 SETRANGE
的隨機訪問向量。GETBIT
和 SETBIT
建立一個Redis支持的 Bloom 過濾器。本系列教程後續會有 字符串 專題會對經常使用命令以及場景進行介紹
Redis 列表是簡單的字符串列表,按照插入順序排序。 你能夠添加一個元素到列表的頭部(左邊)或者尾部(右邊)。
LPUSH
命令插入一個新元素到列表頭部,而 RPUSH
命令 插入一個新元素到列表的尾部。當 對一個空 key
執行其中某個命令時,將會建立一個新表。 相似的,若是一個操做要清空列表,那麼 key
會從對應的 key
空間刪除。這是個很是便利的語義, 由於若是使用一個不存在的 key
做爲參數,全部的列表命令都會像在對一個空表操做同樣。
一個列表最多能夠包含2 ^ 32 - 1個元素(4294967295,每一個表超過40億個元素)。
從時間複雜度的角度來看,Redis 列表主要的特性就是支持時間常數的 插入和靠近頭尾部元素的刪除,即便是須要插入上百萬的條目。 訪問列表兩端的元素是很是快的,但若是你試着訪問一個很是大 的列表的中間元素仍然是十分慢的,由於那是一個時間複雜度爲 O(N) 的操做。
你能夠用 Redis 列表作許多有趣的事,例如你能夠:
LPUSH
去添加新的元素到用戶時間線中,使用 LRANGE
去檢索一些最近插入的條目。LPUSH
和 LTRIM
去建立一個永遠不會超過指定元素數目的列表並同時記住最後的 N 個元素。BLPOP
這樣的阻塞命令。請查看全部可用的列表操做命令獲取更多的信息。本系列教程後續會有 列表 專題會對經常使用命令以及場景進行介紹
Redis 集合是一個無序的字符串合集。你能夠以O(1) 的時間複雜度(不管集合中有多少元素時間複雜度都爲常量)完成 添加,刪除以及測試元素是否存在的操做。
Redis 集合有着不容許相同成員存在的優秀特性。向集合中屢次添加同一元素,在集合中最終只會存在一個此元素。實際上這就意味着,在添加元素前,你並不須要事先進行檢驗此元素是否已經存在的操做。
一個 Redis 列表十分有趣的事是,它們支持一些服務端的命令從現有的集合出發去進行集合運算。 因此你能夠在很短的時間內完成合並(union),求交(intersection), 找出不一樣元素的操做。
一個集合最多能夠包含2 ^ 32 - 1個元素(4294967295,每一個集合超過40億個元素)。
你能夠用 Redis 集合作不少有趣的事,例如你能夠:
SADD
命令把全部擁有 tag 的對象的全部 ID 添加進集合,這樣來表示這個特定的 tag 。若是你想要同時有3個不一樣 tag 的全部對象的全部 ID ,那麼你須要使用 SINTER
。SPOP
或者 SRANDMEMBER
命令隨機地獲取元素。本系列教程後續會有 集合 專題會對經常使用命令以及場景進行介紹
Redis 有序集合和 Redis 集合相似,是不包含 相同字符串的合集。它們的差異是,每一個有序集合 的成員都關聯着一個評分,這個評分用於把有序集 閤中的成員按最低分到最高分排列。
使用有序集合,你能夠很是快地(O(log(N)))完成添加,刪除和更新元素的操做。 由於元素是在插入時就排好序的,因此很快地經過評分(score)或者 位次(position)得到一個範圍的元素。 訪問有序集合的中間元素一樣也是很是快的,所以你可使用有序集合做爲一個沒用重複成員的智能列表。 在這個列表中, 你能夠輕易地訪問任何你須要的東西: 有序的元素,快速的存在性測試,快速訪問集合中間元素!
簡而言之,使用有序集合你能夠很好地完成 不少在其餘數據庫中難以實現的任務。
使用有序集合你能夠:
ZADD
來更新它。你能夠用 ZRANGE
輕鬆地獲取排名靠前的用戶, 你也能夠提供一個用戶名,而後用 ZRANK
取他在排行榜中的名次。 同時使用 ZRANK
和 ZRANGE
你能夠得到與指定用戶有相同分數的用戶名單。 全部這些操做都很是迅速。ZRANGEBYSCORE
能夠簡單快速地檢索到給定年齡段的全部用戶。有序集合或許是最高級的 Redis 數據類型,本系列教程後續會有 有序集合 專題會對經常使用命令以及場景進行介紹
Redis Hashes 是字符串字段和字符串值之間的映射,因此它們是完美的表示對象的數據類型。
一個擁有少許(100個左右)字段的 hash 須要 不多的空間來存儲,因此你能夠在一個小型的 Redis 實例中存儲上百萬的對象。
儘管 Hashes 主要用來表示對象,但它們也可以存儲許多元素,因此你也能夠用 Hashes 來完成許多其餘的任務。
一個 hash 最多能夠包含 2 ^ 32 - 1 個key-value鍵值對(超過40億)。
本系列教程後續會有 哈希 專題會對經常使用命令以及場景進行介紹
Bit arrays (或者說 simply bitmaps): 經過特殊的命令,你能夠將 String 值看成一系列 bits 處理:能夠設置和清除單獨的 bits,數出全部設爲 1 的 bits 的數量,找到最前的被設爲 1 或 0 的 bit,等等。
HyperLogLogs: 這是被用於估計一個 set 中元素數量的機率性的數據結構。
Redis 一樣支持 Bitmaps 和 HyperLogLogs 數據類型,其實是基於字符串的基本類型的數據類型,但有本身的語義。
每種數據結構都有本身底層的內部編碼實現,並且是多種實現,Redis 會在合適的場景選擇合適的內部編碼。這樣設計的好處:
能夠經過 object encoding
命令查詢內部編碼
Redis 是使用了 單線程架構
和 I/O多路複用模型
來實現高性能的內存數據庫服務。
Redis 是單線程來處理命令的,因此命令到達 Redis 後並不會當即執行,而是進入隊列以後逐個執行。對於差很少同時到達的命令執行的順序是沒法肯定的。
因爲命令是逐個執行的,若是某個命令執行時間過長,則會形成其餘命令的阻塞。因此 Redis 是面向快速執行場景的數據庫。
業務名:對象名:id
的格式來聲明鍵,鍵名應該儘量簡短。