我們知道在redis中有5種數(shù)據(jù)類型,之前的文章中我們已經(jīng)介紹過(guò)了String類型,也就是字符串類型,今天我們學(xué)習(xí)第二種數(shù)據(jù)類型,哈希類型。大部分語(yǔ)言基本都提供了哈希類型,如JAVA語(yǔ)言中的Map類型及Python語(yǔ)言中的字典類型等等。雖然語(yǔ)言不同,但它們基本使用都是一樣的。也就是都是鍵值對(duì)結(jié)構(gòu)的。例如:
value={{field1, value1}
下面我們通過(guò)下圖來(lái)直觀感受一下字符串類型和哈希類型的區(qū)別。

Redis中哈希類型都是鍵值對(duì)結(jié)構(gòu)的,所以要特別注意這里的value并不是指的是Redis中的key的value,而是Redis中哈希類型中的field所對(duì)應(yīng)的value。
下面我們還是和介紹字符串類型一樣,先是了解一下Redis中哈希類型的相關(guān)命令。
命令
一. 設(shè)置值
hset key field value

我們看上圖執(zhí)行的命令知道,hset命令也是有返回值的。如果hset命令設(shè)置成功,則返回1,否則則返回0。除此之外Redis也為哈希類型提供了hsetnx命令。在字符串那篇文章中,我們知道,nx命令則表示key不存在的時(shí)候,才能設(shè)置成功,而在Redis中hsetnx命令則表示field不存在的時(shí)候,才能設(shè)置成功。
二. 獲取值
hget key field

我們看hget命令和get有很大的不同,get命令在獲取的時(shí)候,只要寫一個(gè)名字就可以了,而hget命令則要寫兩個(gè)名字,第一個(gè)名字就是key 第二個(gè)名字就是field。除此之外,當(dāng)然key或者field不存在時(shí),返回的結(jié)果都是nil。
三. 刪除field
hdel key field [field ...]

hdel命令刪除的時(shí)候,也會(huì)有返回值,并且這個(gè)返回就是成功刪除field的個(gè)數(shù)。當(dāng)field不存在時(shí),并不會(huì)報(bào)錯(cuò),而是直接返回0。
四. 計(jì)算field個(gè)數(shù)
hlen key

hlen命令返回的就是當(dāng)前key中field的個(gè)數(shù),如果key不存在,則返回0。
五. 批量設(shè)置或獲取field-value
hmget key field [field ...] hmset key field value [field value ...]

hmset命令和hmget命令分別都是批量設(shè)置和獲取值的,hmset命令沒(méi)有什么要注意的,但hmget命令要特別注意,當(dāng)我們獲取一個(gè)不存在的key或者不存在的field時(shí),Redis并不會(huì)報(bào)錯(cuò),而是返回nil。并且有幾個(gè)field不存在,則Redis返回幾個(gè)nil,當(dāng)整個(gè)key都不存在時(shí),則返回全部nil(有幾個(gè)field返回幾個(gè)nil)。
六. 判斷field是否存在
hexists key field

當(dāng)執(zhí)行hexists命令時(shí),如果當(dāng)前key包括field,則返回1,否則返回0。
七. 獲取所有field
hkeys key

八. 獲取所有value
hvals key

九. 獲取所有的field-value
hgetall key

hgetall命令會(huì)返回當(dāng)前key中的所有field-value,并按照順序依次返回,也就是field-value field-value等等。
十. hincrby hincrbyfloat
hincrby key field increment hincrbyfloat key field increment

hincrby命令和incrby命令的使用功能基本一樣,都是對(duì)值進(jìn)行增量操作的。唯一不同的就是incrby命令的作用域key,而hincrby命令的作用域則是field。
十一. 計(jì)算value的字符串長(zhǎng)度
hstrlen key field

hstrlen命令返回的是當(dāng)前key中field中字符串的長(zhǎng)度,如果當(dāng)前key中沒(méi)有field則返回0。
哈希類型命令的時(shí)間復(fù)雜度

內(nèi)部編碼
在Redis哈希類型的內(nèi)部編碼只有兩種它們分別是:
- ziplist(壓縮列表):當(dāng)哈希類型中元素個(gè)數(shù)小于hash-max-ziplist-entries配置(默認(rèn)512個(gè))同時(shí)所有值都小于hash-max-ziplist-value配置(默認(rèn)64字節(jié))時(shí),Redis會(huì)使用ziplist作為哈希的內(nèi)部實(shí)現(xiàn)。
- hashtable(哈希表):當(dāng)上述條件不滿足時(shí),Redis則會(huì)采用hashtable作為哈希的內(nèi)部實(shí)現(xiàn)。
下面我們通過(guò)以下命令來(lái)演示一下ziplist和hashtable這兩種內(nèi)部編碼。
- 當(dāng)field個(gè)數(shù)比較少并且value也不是很大時(shí)候Redis哈希類型的內(nèi)部編碼為ziplist。
- 當(dāng)value中的字節(jié)數(shù)大于64字節(jié)時(shí)(可以通過(guò)hash-max-ziplist-value設(shè)置),內(nèi)部編碼會(huì)由ziplist變成hashtable。
- 因?yàn)樵赗edis中中文的字節(jié)數(shù)比英文的字節(jié)數(shù)大大,正常來(lái)說(shuō),一個(gè)中文占用3個(gè)字節(jié)。
- 當(dāng)field個(gè)數(shù)超過(guò)512(可以通過(guò)hash-max-ziplist-entries參數(shù)設(shè)置),內(nèi)部編碼也會(huì)由ziplist變成hashtable。
- 由于直接創(chuàng)建512個(gè)field不方便,為了更好的驗(yàn)證該功能,我將用程序的方式,動(dòng)態(tài)創(chuàng)建512個(gè)field來(lái)驗(yàn)證此功能,下面為具體的代碼。


以上就是Redis中哈希類型的相關(guān)命令及內(nèi)部編碼,如本文有不正確的地方歡迎指出。