Redis 哈希

哈希

在 Redis 中,哈希類型是指鍵值自己又是一個鍵值對結果,其結構表示爲:html

Redis 結構:python

key -> valueweb

在哈希中 上述的 value 結構:redis

field -> valueshell

使用 json 表示:編程

{key:{field1:value1,field2:value2,...fieldN:valueN}}json

07174426_SDN4.png

經常使用命令

設置值

HSET

自2.0.0起可用。編程語言

時間複雜度: O(1)ui

語法:HSET key field value
說明:

將哈希表 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

獲取值

HGET

自2.0.0起可用。

時間複雜度: O(1)

語法:HSET key field value
說明:

返回哈希表 key 中給定 field 的值。

返回值:

給定 field 的值。

當 給定 field 不存在 或 給定 key 不存在時,返回 nil

示例:
coderknock> HGET user:1 name
"sanchan"
coderknock> HGET user:1 sex
(nil)

HGETALL

自2.0.0起可用。

時間複雜度: O(N), N 爲哈希表的大小。

語法:HSET key field value
說明:

返回哈希表 key 中,全部的 fieldvalue

在返回值裏,緊跟每一個域名 (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命令,該命令會漸進式遍歷哈希類型。

HGETALL

自2.8.0起可用。

時間複雜度: 每次調用 O(1)。O(N)用於完整的迭代,包括足夠的命令調用以使光標返回到0。N是 集合內的元素數量。

語法:HSCAN key cursor [MATCH pattern] [COUNT count]
說明:

獲取哈希中全部的 field-value

參加 SCAN(本系列中有單獨一篇文章介紹)

刪除field

HDEL

自2.0.0起可用。

時間複雜度: O(N), N 爲要刪除的域的數量。

語法: HDEL key field [field ...]
說明:

刪除哈希表 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 個數

HLEN

自2.0.0起可用。

時間複雜度: O(1)

語法: HLEN key
說明:

返回哈希表 key 中域的數量。

返回值:

哈希表中域的數量。

key 不存在時,返回 0

示例:
coderknock> HLEN user:3
(integer) 4
coderknock> HLEN user:1
(integer) 0

批量處理

HGET

自2.0.0起可用。

時間複雜度: O(N), N 爲要獲取的域的數量。

語法: HMGET key field [field ...]
說明:

返回哈希表 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)

HMSET

自2.0.0起可用。

時間複雜度:O(N), Nfield-value 對的數量。

語法:HMSET key field value [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 是否存在

HEXISTS

自2.0.0起可用。

時間複雜度: O(1)

語法: HEXISTS key field
說明:

查看哈希表 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

HKEYS

自2.0.0起可用。

時間複雜度:O(N), N 爲哈希表的大小。

語法: HKEYS key
說明:

返回哈希表 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

HVALS

自2.0.0起可用。

時間複雜度:O(N), N 爲哈希表的大小。

語法:HVALS key
說明:

返回哈希表 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)

計數

HINCRBY HINCRBYFLOAT

自2.0.0起可用。

時間複雜度:O(1)

語法:HINCRBY key field increment
說明:

對哈希表 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,就像 INCRBYINCRBYFLOAT 命令同樣,可是它們的做
用域是 filed

計算 value 的字符串長度

HSTRLEN

自3.2.0起可用。

時間複雜度:O(1)

語法:HVALS key
說明:

返回keyfield 的值的字符串長度。若是 keyfield 不存在,則返回0。

返回值:

返回keyfield 的值的字符串長度。若是 keyfield 不存在,則返回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)。

示例

field 數量較少且沒有較大的 value 時,內部編碼爲 ziplist

127.0.0.1:6379> HMSET ziplistHash k1 v1  k2 v2
OK
127.0.0.1:6379> OBJECT ENCODING ziplistHash
"ziplist"

當有 value 大於 64 字節,內部編碼會由 ziplist 變爲 hashtable

127.0.0.1:6379> HSET ziplistHash k1 qwertyuiopasdfaaaaaaaaaaaaaaaaaaaddddddddddddddddddddsssssssssssffffffffffffffffgggggggggggg
(integer) 0
127.0.0.1:6379> OBJECT ENCODING ziplistHash
"hashtable"

當 field 個數超過 512 時,內部編碼也會由 ziplist 變爲 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"

引用文字

相關文章
相關標籤/搜索