新聞中心

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


咨詢
建站咨詢
