Redis 中哈希結(jié)構(gòu)就如同 Java 的 map 一樣,一個(gè)對(duì)象里面有許多鍵值對(duì),它是特別適合存儲(chǔ)對(duì)象的,如果內(nèi)存足夠大,那么一個(gè) Redis 的 hash 結(jié)構(gòu)可以存儲(chǔ) 2 的 32 次方減 1 個(gè)鍵值對(duì)(40 多億)。
一般而言,不會(huì)使用到那么大的一個(gè)鍵值對(duì),所以我們認(rèn)為 Redis 可以存儲(chǔ)很多的鍵值對(duì)。在 Redis 中,hash 是一個(gè) String 類型的 field 和 value 的映射表,因此我們存儲(chǔ)的數(shù)據(jù)實(shí)際在 Redis 內(nèi)存中都是一個(gè)個(gè)字符串而已。
假設(shè)角色有 3 個(gè)字段:編號(hào)(id)、角色名稱(roleName)和備注(note),這樣就可以使用一個(gè) hash 結(jié)構(gòu)保存它,它的內(nèi)存結(jié)果如表 1 所示。
| role_1|
|--|--|
| field | value |
|---|---|
| id | 89757 |
| roleName | 大內(nèi)密探 |
| 備注 | 007 |
在 Redis 中它就是一個(gè)這樣的結(jié)構(gòu),其中 role_1 代表的是這個(gè) hash 結(jié)構(gòu)在 Redis 內(nèi)存的 key,通過(guò)它就可以找到這個(gè) hash 結(jié)構(gòu),而 hash 結(jié)構(gòu)由一系列的 field 和 value 組成,下面用 Redis 的命令來(lái)保存角色對(duì)象,如圖 1 所示。
上面的命令保存了一個(gè)角色對(duì)象。在 Redis 中,角色對(duì)象是通過(guò)鍵 role_1 來(lái)索引的,而角色本身是一個(gè)如表 1 所示的 hash 結(jié)構(gòu)。hash 的鍵值對(duì)在內(nèi)存中是一種無(wú)序的狀態(tài),我們可以通過(guò)鍵找到對(duì)應(yīng)的值。
Redis hash 結(jié)構(gòu)命令,如表 2 所示。
| 命令 | 說(shuō)明 | 備注 |
|---|---|---|
| hdel key field1[field2......] | 刪除 hash 結(jié)構(gòu)中的某個(gè)(些)字段 | 可以進(jìn)行多個(gè)字段的刪除 |
| hexists key field | 判斷 hash 結(jié)構(gòu)中是否存在 field 字段 | 存在返回 1,否則返回 0 |
| hgetall key | 獲取所有 hash 結(jié)構(gòu)中的鍵值 | 返回鍵和值 |
| hincrby key field increment | 指定給 hash 結(jié)構(gòu)中的某一字段加上一個(gè)整數(shù) | 要求該字段也是整數(shù)字符串 |
| hincrbyfloat key field increment | 指定給 hash 結(jié)構(gòu)中的某一字段加上一個(gè)浮點(diǎn)數(shù) | 要求該字段是數(shù)字型字符串 |
| hkeys key | 返回 hash 中所有的鍵 | |
| hlen key | 返回 hash 中鍵值對(duì)的數(shù)量 | |
| hmget key field1[field2......] | 返回 hash 中指定的鍵的值,可以是多個(gè) | 依次返回值 |
| hmset key field1 value1 [field2 field2......] | hash 結(jié)構(gòu)設(shè)置多個(gè)鍵值對(duì) | |
| hset key filed value | 在 hash 結(jié)構(gòu)中設(shè)置鍵值對(duì) | 單個(gè)設(shè)值 |
| hsetnx key field value | 當(dāng) hash 結(jié)構(gòu)中不存在對(duì)應(yīng)的鍵,才設(shè)置值 | |
| hvals key | 獲取 hash 結(jié)構(gòu)中所有的值 |
從表 2 中可以看出,在 Redis 中的哈希結(jié)構(gòu)和字符串有著比較明顯的不同。
首先,命令都是以 h 開(kāi)頭,代表操作的是 hash 結(jié)構(gòu)。其次,大多數(shù)命令多了一個(gè)層級(jí) field,這是 hash 結(jié)構(gòu)的一個(gè)內(nèi)部鍵,也就是說(shuō) Redis 需要通過(guò) key 索引到對(duì)應(yīng)的 hash 結(jié)構(gòu),再通過(guò) field 來(lái)確定使用 hash 結(jié)構(gòu)的哪個(gè)鍵值對(duì)。
下面通過(guò) Redis 的這些操作命令來(lái)展示如何使用它們,如圖 2 所示。
從圖 2 中可以看到Redis 關(guān)于哈希結(jié)構(gòu)的相關(guān)命令。這里需要注意的是:
哈希結(jié)構(gòu)的大小,如果哈希結(jié)構(gòu)是個(gè)很大的鍵值對(duì),那么使用它要十分注意,尤其是關(guān)于 hkeys、hgetall、hvals 等返回所有哈希結(jié)構(gòu)數(shù)據(jù)的命令,會(huì)造成大量數(shù)據(jù)的讀取。這需要考慮性能和讀取數(shù)據(jù)大小對(duì) JVM 內(nèi)存的影響。
對(duì)于數(shù)字的操作命令 hincrby 而言,要求存儲(chǔ)的也是整數(shù)型的字符串,對(duì)于 hincrbyfloat 而言,則要求使用浮點(diǎn)數(shù)或者整數(shù),否則命令會(huì)失敗。