在 Redis 中,哈希類型是指鍵值自己又是一個鍵值對結果,其結構表示爲:html
Redis 結構:python
key -> value
web
在哈希中 上述的 value 結構:redis
field -> value
shell
使用 json 表示:編程
{key:{field1:value1,field2:value2,...fieldN:valueN}}
json
自2.0.0起可用。編程語言
時間複雜度: O(1)ui
將哈希表 key
中的域 field
的值設爲 value
。編碼
若是 key
不存在,一個新的哈希表被建立並進行 HSET 操做。
若是域 field
已經存在於哈希表中,舊值將被覆蓋。
若是 field
是哈希表中的一個新建域,而且值設置成功,返回 1
。
若是哈希表中域 field
已經存在且舊值已被新值覆蓋,返回 0
。
coderknock> HSET user:1 name sanchan (integer) 1 coderknock> HSET user:1 age 18 (integer) 1 coderknock> HSET user:1 age 24 (integer) 0
此外Redis提供了hsetnx命令,它們的關係就像 SET 和 SETNX 命令同樣,只不過做用域由 key
變爲 field
。
自2.0.0起可用。
時間複雜度: O(1)
返回哈希表 key
中給定 field
的值。
給定 field
的值。
當 給定 field
不存在 或 給定 key
不存在時,返回 nil
。
coderknock> HGET user:1 name "sanchan" coderknock> HGET user:1 sex (nil)
自2.0.0起可用。
時間複雜度: O(N),
N
爲哈希表的大小。
返回哈希表 key
中,全部的 field
和 value
。
在返回值裏,緊跟每一個域名 (field name) 以後是域的值 (value) ,因此返回值的長度是哈希表大小的兩倍。
以列表形式返回哈希表的域和域的值。
若 key
不存在,返回空列表。
coderknock> HGETALL user:1 1) "name" # field 2) "sanchan" # value 3) "age" #field 4) "24" # value #若 key 不存在,返回空列表 coderknock> HGETALL user:2 (empty list or set)
在使用 HGETALL
時,若是哈希元素個數比較多,會存在阻塞 Redis 的可能。
若是開發人員只須要獲取部分 field
,可使用 HMGET
(後面有介紹),若是必定要獲取所有 field-value
,可使用 HSCAN
命令,該命令會漸進式遍歷哈希類型。
自2.8.0起可用。
時間複雜度: 每次調用 O(1)。O(N)用於完整的迭代,包括足夠的命令調用以使光標返回到0。
N是
集合內的元素數量。
獲取哈希中全部的 field-value
SCAN
(本系列中有單獨一篇文章介紹)field
自2.0.0起可用。
時間複雜度: O(N),
N
爲要刪除的域的數量。
刪除哈希表 key
中的一個或多個指定 field
,不存在的 field
將被忽略。
在 Redis 2.4 如下的版本里, HDEL 每次只能刪除單個域,若是你須要在一個原子時間內刪除多個域,請將命令包含在 MULTI / EXEC塊內。
在 Redis 2.4 (包含)及以上版本中能夠一次傳入多個 fiele
。
被成功移除的 field
的數量,不包括被忽略的 field
。若是 key
不存在,則將其視爲空哈希,返回 0
。
coderknock> HDEL user:1 name (integer) 1 coderknock> HGETALL user:1 1) "age" 2) "24" # 刪除的 key 不存在 coderknock> HDEL user:2 name (integer) 0 coderknock> HGETALL user:3 1) "name" 2) "coderknock" 3) "user" 4) "sanchan" 5) "age" 6) "24" 7) "website" 8) "http://www.coderknock.com" 9) "name2" 10) "test" 11) "age2" 12) "1" # 刪除多個 field 其中 sex 不存在 coderknock> HDEL user:3 name2 sex age2 (integer) 2 coderknock> HGETALL user:3 1) "name" 2) "coderknock" 3) "user" 4) "sanchan" 5) "age" 6) "24" 7) "website" 8) "http://www.coderknock.com" # 當一個 key 中全部的 field 被刪除則改 key 也會被刪除 coderknock> HDEL user:1 age (integer) 1 coderknock> EXISTS user:1 (integer) 0
field
個數自2.0.0起可用。
時間複雜度: O(1)
返回哈希表 key
中域的數量。
哈希表中域的數量。
當 key
不存在時,返回 0
。
coderknock> HLEN user:3 (integer) 4 coderknock> HLEN user:1 (integer) 0
自2.0.0起可用。
時間複雜度: O(N),
N
爲要獲取的域的數量。
返回哈希表 key
中,一個或多個給定域的值。
若是給定的域不存在於哈希表,那麼返回一個 nil
值。
由於不存在的 key
被看成一個空哈希表來處理,因此對一個不存在的 key
進行 HMGET 操做將返回一個只帶有 nil
值的表。
一個包含多個給定域的關聯值的表,表值的排列順序和給定域參數的請求順序同樣。
key
不存在則返回 nil
。
coderknock> HMGET user:3 website name age name2 user 1) "http://www.coderknock.com" 2) "coderknock" 3) "24" 4) (nil) # 不存在的域返回nil值 5) "sanchan" # key 不存在 返回 nil coderknock> HMGET user:4 name 1) (nil)
自2.0.0起可用。
時間複雜度:O(N),
N
爲field-value
對的數量。
同時將多個 field-value
(域-值)對設置到哈希表 key
中。
此命令會覆蓋哈希表中已存在的域。
若是 key
不存在,一個空哈希表被建立並執行 HMSET 操做。
若是命令執行成功,返回 OK
。
當 key
不是哈希表 (hash) 類型時,返回一個錯誤。
# embstrKey 不是哈希,因此會報錯 coderknock> HMSET embstrKey name 1 (error) WRONGTYPE Operation against a key holding the wrong kind of value coderknock> HMSET user:5 name sanchan website https://www.coderknock.com OK coderknock> HGETALL user:5 1) "name" 2) "sanchan" 3) "website" 4) "https://www.coderknock.com" coderknock> HMSET user:5 user sanchan name coverSanchan OK coderknock> HGETALL user:5 1) "name" 2) "coverSanchan" # name 被覆蓋 3) "website" 4) "https://www.coderknock.com" 5) "user" 6) "sanchan"
field
是否存在自2.0.0起可用。
時間複雜度: O(1)
查看哈希表 key
中,給定域 field
是否存在。
若是哈希表含有給定域,返回 1
。
若是哈希表不含有給定域,或 key
不存在,返回 0
。
coderknock> HEXISTS user:5 name2 (integer) 0 coderknock> HEXISTS user:5 name (integer) 1 # embstrKey 不是哈希因此會報錯 coderknock> HEXISTS embstrKey name (error) WRONGTYPE Operation against a key holding the wrong kind of value # 不存在 a 這個 key coderknock> HEXISTS a name (integer) 0
field
自2.0.0起可用。
時間複雜度:O(N),
N
爲哈希表的大小。
返回哈希表 key
中的全部域。
一個包含哈希表中全部域的表。
當 key
不存在時,返回一個空表。
coderknock> HKEYS user:5 1) "name" 2) "website" 3) "user" # embstrKey 不是哈希 coderknock> HKEYS embstrKey (error) WRONGTYPE Operation against a key holding the wrong kind of value # a 這個 key 不存在 coderknock> HKEYS a (empty list or set)
value
自2.0.0起可用。
時間複雜度:O(N),
N
爲哈希表的大小。
返回哈希表 key
中全部域的值。
一個包含哈希表中全部值的表。
當 key
不存在時,返回一個空表。
coderknock> HVALS user:5 1) "coverSanchan" 2) "https://www.coderknock.com" # embstrKey 不是哈希 coderknock> HVALS embstrKey (error) WRONGTYPE Operation against a key holding the wrong kind of value # a 這個 key 不存在 coderknock> HVALS a (empty list or set)
自2.0.0起可用。
時間複雜度:O(1)
對哈希表 key
中的域 field
的值進行增量 increment
操做,相似 字符串操做中的 INCR
。
增量也能夠爲負數,至關於對給定域進行減法操做。
若是 key
不存在,一個新的哈希表被建立並執行 HINCRBY 命令。
若是域 field
不存在,那麼在執行命令前,域的值被初始化爲 0
。
對一個儲存字符串值的域 field
執行 HINCRBY 命令將形成一個錯誤。
本操做的值被限制在 64 位(bit)有符號數字表示以內。
執行 HINCRBY 命令以後,哈希表 key
中域 field
的值。
# increment 爲正數 coderknock> HEXISTS coderknockCounter view_count # 對空域進行設置 (integer) 0 coderknock> HINCRBY coderknockCounter view_count 1000 (integer) 1000 coderknock> HGETALL coderknockCounter 1) "view_count" 2) "1000" # increment 爲負數 coderknock> HINCRBY coderknockCounter view_count -1100 (integer) -100 coderknock> HGETALL coderknockCounter 1) "view_count" 2) "-100" coderknock> # 嘗試對字符串值的域執行HINCRBY命令 coderknock> HSET strHash strField sanchan # 設定一個字符串值 (integer) 1 coderknock> HGETALL strHash 1) "strField" 2) "sanchan" coderknock> HINCRBY strHash strField 1 # 命令執行失敗,錯誤。 (error) ERR hash value is not an integer coderknock> HGETALL strHash # 原值不變 1) "strField" 2) "sanchan"
HINCRBY
和 HINCRBYFLOAT
,就像 INCRBY
和 INCRBYFLOAT
命令同樣,可是它們的做
用域是 filed
。
value
的字符串長度自3.2.0起可用。
時間複雜度:O(1)
返回key
中 field
的值的字符串長度。若是 key
或 field
不存在,則返回0。
返回key
中 field
的值的字符串長度。若是 key
或 field
不存在,則返回0。
coderknock> HGETALL user:5 1) "name" 2) "coverSanchan" 3) "website" 4) "https://www.coderknock.com" 5) "user" 6) "sanchan" coderknock> HSTRLEN user:5 name (integer) 12 # 查詢哈希中不存在的 field coderknock> HSTRLEN user:5 non (integer) 0 # 查詢不存在的 key coderknock> HSTRLEN a a (integer) 0 # 查詢非哈希 key coderknock> HSTRLEN embstrKey name (error) WRONGTYPE Operation against a key holding the wrong kind of value
哈希類型的內部編碼有兩種:
ziplist(壓縮列表):當哈希類型元素個數小於 hash-max-ziplist-entries
配置(默認512個)、同時全部值都小於 hash-max-ziplist-value
配置(默認64字節)時,Redis 會使用 ziplist 做爲哈希的內部實現,ziplist 使用更加緊湊的結構實現多個元素的連續存儲,因此比 hashtable 更加節省內存。
hashtable(哈希表):當哈希類型沒法知足 ziplist 的條件時,Redis 會使用 hashtable 做爲哈希的內部實現,由於此時 ziplist 的讀寫效率會降低,而 hashtable 的讀寫時間複雜度爲O(1)。
127.0.0.1:6379> HMSET ziplistHash k1 v1 k2 v2 OK 127.0.0.1:6379> OBJECT ENCODING ziplistHash "ziplist"
127.0.0.1:6379> HSET ziplistHash k1 qwertyuiopasdfaaaaaaaaaaaaaaaaaaaddddddddddddddddddddsssssssssssffffffffffffffffgggggggggggg (integer) 0 127.0.0.1:6379> OBJECT ENCODING ziplistHash "hashtable"
這裏咱們使用 python 進行批量操做(與手動插入效果相同,只是數據量較大手動插入比較麻煩,使用其餘編程語言也可) pip install redis
須要先安裝對應庫。
import redis r = redis.StrictRedis(host='127.0.0.1', password='admin123', port=6379, db=0) dict = {} for i in range(513): dict["field" + str(i)] = "value " + str(i) r.hmset("hashtableHash", dict) # 也可使用這個命令查詢內部編碼 r.object("ENCODING","hashtableHash")
查詢內部編碼
127.0.0.1:6379> OBJECT ENCODING hashtableHash "hashtable"
使用上面的 python 修改 range 長度發現:
127.0.0.1:6379> HLEN hashtableHash2 (integer) 511 127.0.0.1:6379> OBJECT ENCODING hashtableHash2 "ziplist" 127.0.0.1:6379> HLEN hashtableHash1 (integer) 512 127.0.0.1:6379> OBJECT ENCODING hashtableHash1 "ziplist"
引用文字