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