Redis學(xué)習(xí)筆記:hash類(lèi)型內(nèi)部編碼及其應(yīng)用場(chǎng)景

一、概述

在Redis中,hash類(lèi)型是指鍵值本身又是一個(gè)鍵值對(duì)結(jié)構(gòu),形如 value = {{field1,value1},....,{fieldN,valueN}},注意區(qū)分在哈希類(lèi)型中的映射關(guān)系(field-value)這里的value指的是field對(duì)應(yīng)的值,而不是key對(duì)應(yīng)的值。
hash類(lèi)型與String類(lèi)型對(duì)比如下:


hash類(lèi)型.png

二、常用命令

  1. 設(shè)置值
  • hset key field value:如果設(shè)置成功會(huì)返回1,反之返回0,另外Redis提供了hsetnx命令,其關(guān)系就像set與setnx命令一樣,只是作用域由鍵變成field;
  • hmset key field [field value]:批量設(shè)置field-value;
  1. 獲取值
  • hget key field:獲取單個(gè)value,如果key或field不存在則返回nil;
  • hmget key field :批量獲取field-value;
  • hkeys key:獲取所有的field;
  • hvals key:獲取所有的value;
  • hgetall key:獲取所有的field-value;
  1. 刪除field
  • hdel key field [field...]:刪除一個(gè)或者多個(gè)field,返回結(jié)果為成功刪除field的個(gè)數(shù);
  1. 其他命令
  • hlen key :計(jì)算field的個(gè)數(shù);
  • hexists key field:判斷field是否存在;

三、內(nèi)部編碼

hash類(lèi)型的內(nèi)部編碼有兩種:

  • ziplist(壓縮列表):當(dāng)哈希類(lèi)型元素個(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),ziplist使用更加緊湊的結(jié)構(gòu)實(shí)現(xiàn)多個(gè)元素的連續(xù)存儲(chǔ),所以在節(jié)省內(nèi)存方面比hashtable更加優(yōu)秀;
  • hashtable(哈希表):當(dāng)當(dāng)哈希類(lèi)型無(wú)法滿(mǎn)足ziplist的條件時(shí),Redis會(huì)使用hashtable作為哈希的內(nèi)部實(shí)現(xiàn),因?yàn)榇藭r(shí)ziplist的讀寫(xiě)效率會(huì)下降,而hashtable的讀寫(xiě)時(shí)間復(fù)雜度為O(1);

可以使用object encoding hashkey查看當(dāng)前hash的內(nèi)部編碼是哪種。

四、使用場(chǎng)景

緩存設(shè)計(jì)

hash類(lèi)型也可以用來(lái)作為緩存信息,相比于使用字符串序列化緩存,hash類(lèi)型變得更加直觀,并且在更新操作上會(huì)更加便捷;可以將每個(gè)用戶(hù)的id定義為鍵后綴,多對(duì)field-value對(duì)應(yīng)每個(gè)用戶(hù)的屬性,一種可能的實(shí)現(xiàn)如下:

UserInfo getUserInfo(long id){
    //用戶(hù)id作為后綴
    userRedisKey = "user:info:"+ id;
    //使用hgetall獲取所有用戶(hù)信息映射關(guān)系
    userInfoMap = redis.hgetAll(userRedisKey);
    UserInfo userInfo;
    if(userInfoMap != null){
        //將映射關(guān)系轉(zhuǎn)換為UserInfo
        userInfo = transferMapToUserInfo(userInfoMap);
    }else{
        //從MySQL中獲取用戶(hù)信息
        userInfo = mysql.get(id);
        //將userInfo變?yōu)橛成潢P(guān)系使用hmset保存到Redis中
        redis.hmset(userRedisKey,transferUserInfoToMap(userInfo));
        //添加過(guò)期時(shí)間
        redis.expire(userRedisKey,3600);
    }
    return userInfo;
}

使用哈希類(lèi)型和關(guān)系型數(shù)據(jù)庫(kù)的不同之處:

  • hash類(lèi)型是稀疏的,而關(guān)系數(shù)據(jù)庫(kù)時(shí)完全結(jié)構(gòu)化的,例如hash類(lèi)型每個(gè)鍵都可以有不同的field,而關(guān)系數(shù)據(jù)庫(kù)一旦添加新的列,所有行都要為其設(shè)置值(含null);
  • 關(guān)系型數(shù)據(jù)庫(kù)可以作復(fù)雜的關(guān)系查詢(xún),而Redis去模擬關(guān)系型復(fù)雜查詢(xún)開(kāi)發(fā)困難,維護(hù)成本高;

緩存實(shí)現(xiàn)方法優(yōu)劣分析:

1.原生字符串類(lèi)型:每個(gè)屬性一個(gè)鍵;

set user:1:name vechace

set user:1:age 22

set user:1:city shenzhen

優(yōu)點(diǎn):簡(jiǎn)單直觀,每個(gè)屬性都支持更新操作;

缺點(diǎn):占用過(guò)多的鍵,內(nèi)存占用量較大,同時(shí)用戶(hù)信息內(nèi)聚性比較差,一般不會(huì)在生產(chǎn)環(huán)境中直接使用;

2.序列化字符串類(lèi)型:將用戶(hù)信息序列化后用一個(gè)鍵保存;

set user:1 serialize(userInfo)

優(yōu)點(diǎn):簡(jiǎn)化編程,合理使用序列化可以提高內(nèi)存的使用效率;

缺點(diǎn):序列化和反序列化有一定的開(kāi)銷(xiāo),同時(shí)每次更新屬性都需要把全部數(shù)據(jù)取出,進(jìn)行反序列化,更新后再序列化到Redis中;

3.hash類(lèi)型:每個(gè)用戶(hù)屬性使用一對(duì)field-value,但是只用一個(gè)鍵保存;

hmset user:1 name vechace age 22 city shenzhen

優(yōu)點(diǎn):簡(jiǎn)單直觀,合理使用也可以減少內(nèi)存空間的使用;

缺點(diǎn):要控制hash在ziplist和hashtable兩種內(nèi)部編碼的轉(zhuǎn)換,hashtable會(huì)消耗更多的內(nèi)存。

感謝閱讀~

參考資料:


1、《Redis開(kāi)發(fā)與運(yùn)維》

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Redis的內(nèi)存優(yōu)化 聲明:本文內(nèi)容來(lái)自《Redis開(kāi)發(fā)與運(yùn)維》一書(shū)第八章,如轉(zhuǎn)載請(qǐng)聲明。 Redis所有的數(shù)據(jù)都...
    meng_philip123閱讀 19,081評(píng)論 2 29
  • 參考來(lái)源 Redis的內(nèi)存優(yōu)化 Redis所有的數(shù)據(jù)都在內(nèi)存中,而內(nèi)存又是非常寶貴的資源。對(duì)于如何優(yōu)化內(nèi)存使用一直...
    秦漢郵俠閱讀 1,374評(píng)論 0 2
  • 聲明:本文內(nèi)容來(lái)自《Redis開(kāi)發(fā)與運(yùn)維》一書(shū)第八章,如轉(zhuǎn)載請(qǐng)聲明。Redis所有的數(shù)據(jù)都在內(nèi)存中,而內(nèi)存又是非常...
    yoqu閱讀 1,623評(píng)論 0 2
  • 1.數(shù)據(jù)結(jié)構(gòu) 1.1字符串 字符串類(lèi)型的值實(shí)際可以是字符串、數(shù)字(整數(shù),浮點(diǎn)數(shù)),甚至是二進(jìn)制(圖片、視頻)...
    Sponge1128閱讀 1,471評(píng)論 0 0
  • 笑顏于粵閱讀 156評(píng)論 0 0

友情鏈接更多精彩內(nèi)容