新聞中心

創(chuàng)新互聯(lián)建站網(wǎng)絡(luò)公司擁有10多年的成都網(wǎng)站開(kāi)發(fā)建設(shè)經(jīng)驗(yàn),上千多家客戶(hù)的共同信賴(lài)。提供網(wǎng)站制作、網(wǎng)站建設(shè)、網(wǎng)站開(kāi)發(fā)、網(wǎng)站定制、買(mǎi)友情鏈接、建網(wǎng)站、網(wǎng)站搭建、成都響應(yīng)式網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)師打造企業(yè)風(fēng)格,提供周到的售前咨詢(xún)和貼心的售后服務(wù)
Redis hash 特別適合于存儲(chǔ)對(duì)象。一個(gè) filed/value 可以看做是表格中一條數(shù)據(jù)記錄;而一個(gè) key 可以對(duì)應(yīng)多條數(shù)據(jù)。下面舉一個(gè)例子,使用 hash 類(lèi)型存儲(chǔ)表格中的數(shù)據(jù),這里以
user為 key,
id:1為字段,
name:Cao為 value:
| id | name |
|---|---|
| 1 | Cao |
| 2 | Zhao |
命令實(shí)例演示:
#以u(píng)ser為key,設(shè)置 id+序號(hào)為字段,name+名字為值 127.0.0.1:6379> HMSET user id:1 name:Cao id:2 name:Zhao OK # 查詢(xún) user 這個(gè)key下所有的數(shù)據(jù),并以字符串的形式將值返回 127.0.0.1:6379> HGETALL user 1) "id:1" 2) "name:Cao" 3) "id:2" 4) "name:Zhao"
注意:當(dāng)我們對(duì) value 進(jìn)行查詢(xún)時(shí),這個(gè)值只能以字符串的形式返回。
通過(guò)上述方法,我們就把表格中的數(shù)據(jù)存儲(chǔ)在了內(nèi)存中。Redis hash 的存儲(chǔ)結(jié)構(gòu)如下圖所示:
圖1:hash存儲(chǔ)結(jié)構(gòu)圖
一個(gè) hash 類(lèi)型的 key 最多可以存儲(chǔ) 2^32-1(約 40 億個(gè))字段/值。同時(shí) Redis hash 會(huì)為這個(gè) key 額外儲(chǔ)存一些附加的管理信息,比如這個(gè)鍵的類(lèi)型、最后一次訪(fǎng)問(wèn)這個(gè)鍵的時(shí)間等,所以 hash 鍵越來(lái)越多時(shí),Redis 耗費(fèi)在管理信息方面的內(nèi)存就越多。當(dāng) hash 類(lèi)型移除最后一個(gè)元素后,該存儲(chǔ)結(jié)構(gòu)就會(huì)被自動(dòng)刪除,其占用內(nèi)存也會(huì)被系統(tǒng)回收。
初識(shí)hash類(lèi)型
hash 類(lèi)型是 Redis 常用數(shù)據(jù)類(lèi)型之一,其底層存儲(chǔ)結(jié)構(gòu)有兩種實(shí)現(xiàn)方式。
第一種,當(dāng)存儲(chǔ)的數(shù)據(jù)量較少的時(shí),hash 采用 ziplist 作為底層存儲(chǔ)結(jié)構(gòu),此時(shí)要求符合以下兩個(gè)條件:
- 哈希對(duì)象保存的所有鍵值對(duì)(鍵和值)的字符串長(zhǎng)度總和小于 64 個(gè)字節(jié)。
- 哈希對(duì)象保存的鍵值對(duì)數(shù)量要小于 512 個(gè)。
當(dāng)無(wú)法滿(mǎn)足上述條件時(shí),hash 就會(huì)采用第二種方式來(lái)存儲(chǔ)數(shù)據(jù),也就是 dict(字典結(jié)構(gòu)),該結(jié)構(gòu)類(lèi)似于 Java 的 HashMap,是一個(gè)無(wú)序的字典,并采用了數(shù)組和鏈表相結(jié)合的方式存儲(chǔ)數(shù)據(jù)。在 Redis 中,dict 是基于哈希表算法實(shí)現(xiàn)的,因此其查找性能非常高效,其時(shí)間復(fù)雜度為 O(1)。
哈希表又稱(chēng)散列表,其初衷是將數(shù)據(jù)映射到數(shù)組中的某個(gè)位置上,這樣就能夠通過(guò)數(shù)組下標(biāo)來(lái)訪(fǎng)問(wèn)該數(shù)據(jù),從而提高數(shù)據(jù)的查找效率。下面通過(guò)一個(gè)示例,了解一下到底什么是哈希表。
現(xiàn)在有 1/5/8/ 三個(gè)數(shù)字,你需要把這三個(gè)數(shù)字映射到數(shù)組中,由于哈希表規(guī)定必須使用下標(biāo)來(lái)訪(fǎng)問(wèn)數(shù)據(jù),因此你需要構(gòu)建一個(gè) 0 到 8 的數(shù)組,如下所示:
如上圖所示,我們把待查找的數(shù)字,在相應(yīng)的下標(biāo)數(shù)組上標(biāo)記出來(lái),它們之間一一對(duì)應(yīng)。雖然這樣做能實(shí)現(xiàn)元素的查找,但卻很浪費(fèi)存儲(chǔ)空間,并且查找效率也不高。而如果采用哈希表的話(huà),我們只需要申請(qǐng)一個(gè)長(zhǎng)度為 3 的數(shù)組(與待查找的元素個(gè)數(shù)相同),如下圖所示:
將 1/5/8 分別對(duì)數(shù)組長(zhǎng)度 3 做取模運(yùn)算,然后把它們指向運(yùn)算結(jié)果對(duì)應(yīng)的數(shù)組
槽位,這樣就把一組離散的數(shù)據(jù)映射到了連續(xù)的空間中,從而在最大限度上提高了空間的利用率,并且也提高了元素的查找效率。但是你可能會(huì)發(fā)現(xiàn)一個(gè)問(wèn)題,數(shù)字 5、8 竟然映射到同一個(gè)槽位上,這樣就導(dǎo)致其中一個(gè)數(shù)字無(wú)法查找到。上述這種情況在實(shí)際中也會(huì)遇到,我們把它稱(chēng)為“哈希沖突”或者“哈希碰撞”。
有許多方法可以解決“哈希沖突”,比如開(kāi)放地址法、鏈表地址法,再次散列法等,而 Redis 采用是鏈表地址法。這里我們只對(duì)鏈表地址法做簡(jiǎn)單介紹,很容易理解,這種方法就是將有沖突的數(shù)據(jù)使用鏈表把它們串聯(lián)起來(lái),這樣即使發(fā)生了沖突,也可以將數(shù)據(jù)存儲(chǔ)在一起,最后,通過(guò)遍歷鏈表的方式就找到上述發(fā)生“沖突”的數(shù)據(jù)。如下所示:
如果值是字符串的話(huà),就需要通過(guò)哈希函數(shù)將字符串轉(zhuǎn)換成具體的數(shù)值,然后再對(duì)其進(jìn)行映射。關(guān)于哈希函數(shù)這里不做過(guò)多介紹,如果感興趣可以自行研究。
常用命令匯總
| 命令 | 說(shuō)明 |
|---|---|
| HDEL key field2 [field2] | 用于刪除一個(gè)或多個(gè)哈希表字段。 |
| HEXISTS key field | 用于確定哈希表字段是否存在。 |
| HGET key field | 獲取 key 關(guān)聯(lián)的哈希字段的值。 |
| HGETALL key | 獲取 key 關(guān)聯(lián)的所有哈希字段值。 |
| HINCRBY key field increment | 給 key 關(guān)聯(lián)的哈希字段做整數(shù)增量運(yùn)算 。 |
| HINCRBYFLOAT key field increment | 給 key 關(guān)聯(lián)的哈希字段做浮點(diǎn)數(shù)增量運(yùn)算 。 |
| HKEYS key | 獲取 key 關(guān)聯(lián)的所有字段和值。 |
| HLEN key | 獲取 key 中的哈希表的字段數(shù)量。 |
| HMSET key field1 value1 [field2 value2 ] | 在哈希表中同時(shí)設(shè)置多個(gè) field-value(字段-值) |
| HMGET key field1 [field2] | 用于同時(shí)獲取多個(gè)給定哈希字段(field)對(duì)應(yīng)的值。 |
| HSET key field value | 用于設(shè)置指定 key 的哈希表字段和值(field/value)。 |
| HSETNX key field value | 僅當(dāng)字段 field 不存在時(shí),設(shè)置哈希表字段的值。 |
| HVALS key | 用于獲取哈希表中的所有值。 |
| HSCAN key cursor | 迭代哈希表中的所有鍵值對(duì),cursor 表示游標(biāo),默認(rèn)為 0。 |
基本命令操作
示例演示:微博上好友關(guān)注時(shí)間的場(chǎng)景,這里以用戶(hù) ID 作為 key(user:10),field 字段表示好友的 ID,value 則代表好友關(guān)注用戶(hù)(user:10)的時(shí)間。
#設(shè)置單個(gè)字段 127.0.0.1:6379> HSET user:10 user:1 20201001 (integer) 1 #同時(shí)設(shè)置多個(gè)字段 127.0.0.1:6379> HMSET user:10 user:2 20201002 user:3 20201004 user:4 20201018 OK #查詢(xún)單個(gè)字段 127.0.0.1:6379> HGET user:10 user:2 "20201002" #查詢(xún)所有字段 127.0.0.1:6379> HGETALL user:10 1) "user:1" 2) "20201001" 3) "user:2" 4) "20201002" 5) "user:3" 6) "20201004" 7) "user:4" 8) "20201018" 127.0.0.1:6379> HKEYS user:10 1) "user:1" 2) "user:2" 3) "user:3" 4) "user:4" #返回字段個(gè)數(shù) 127.0.0.1:6379> HLEN user:10 (integer) 4 #返回所有字段值 127.0.0.1:6379> HVALS user:10 1) "20201001" 2) "20201002" 3) "20201004" 4) "20201018" #迭代hash的key鍵 127.0.0.1:6379> HSCAN user:10 0 1) "0" 2) 1) "user:1" 2) "20201001" 3) "user:2" 4) "20201002" 5) "user:3" 6) "20201004" 7) "user:4" 8) "20201018" #判斷字段是否存在,存在返回1,不存在返回0 127.0.0.1:6379> HEXISTS user:10 user:4 (integer) 1 127.0.0.1:6379> HEXISTS user:10 user:5 (integer) 0
在線(xiàn)練習(xí)工具:https://try.redis.io/
查看更多命令:https://redis.io/commands
網(wǎng)站欄目:Redishash哈希散列(圖解)
本文路徑:http://www.5511xx.com/article/dhgdico.html


咨詢(xún)
建站咨詢(xún)
