hash類型是string類型的field和value映射表,或者說是一個string集合,它特別適合存儲對象,相比較而言,將一個對象類型存儲在hash類型里要比存儲在string類型類,占用更小的內存空間,并方便存取整個對象。
在Redis中,哈希類型是指鍵值本身又是一個鍵值對結構,形如:value={{field1,value1},{field2,value2},{fieldN,valueN}},
常用命令:??
hget,hset,hgetall?等。?
應用場景:
我們簡單舉個實例來描述下Hash的應用場景,比如我們要存儲一個用戶信息對象數據,包含以下信息:
用戶ID,為查找的key,
存儲的value用戶對象包含姓名name,年齡age,生日birthday等信息。
如果用普通的key/value結構來存儲,主要有以下2種存儲方式:
第一種方式將用戶ID作為查找key,把其他信息封裝成一個對象以序列化的方式存儲,
如:set?u001?“李三,18,20010101”
這種方式的缺點是,增加了序列化/反序列化的開銷,并且在需要修改其中一項信息時,需要把整個對象取回,并且修改操作需要對并發進行保護,引入CAS等復雜問題。
第二種方法是這個用戶信息對象有多少成員就存成多少個key-value對,用用戶ID+對應屬性的名稱作為唯一標識來取得對應屬性的值,如:mset?user:001:name?“李三?“user:001:age18?user:001:birthday?“20010101”
雖然省去了序列化開銷和并發問題,但是用戶ID為重復存儲,如果存在大量這樣的數據,內存浪費還是非常可觀的。
那么Redis提供的Hash很好的解決了這個問題,Redis的Hash實際是內部存儲的Value為一個HashMap,并提供了直接存取這個Map成員的接口。
如:hmset?user:001?name?“李三”?age?18?birthday?“20010101”?
也就是說,Key仍然是用戶ID,value是一個Map,這個Map的key是成員的屬性名,value是屬性值,這樣對數據的修改和存取都可以直接通過其內部Map的Key(Redis里稱內部Map的key為field),?也就是通過key(用戶ID)?+?field(屬性標簽)?操作對應屬性數據了,既不需要重復存儲數據,也不會帶來序列化和并發修改控制的問題。很好的解決了問題。這里同時需要注意,Redis提供了接口(hgetall)可以直接取到全部的屬性數據,但是如果內部Map的成員很多,那么涉及到遍歷整個內部Map的操作,由于Redis單線程模型的緣故,這個遍歷操作可能會比較耗時,而另其它客戶端的請求完全不響應,這點需要格外注意。
實現方式:上面已經說到Redis?Hash對應Value內部實際就是一個HashMap,實際這里會有2種不同實現,這個Hash的成員比較少時Redis為了節省內存會采用類似一維數組的方式來緊湊存儲,而不會采用真正的HashMap結構,對應的value?redisObject的encoding為zipmap,當成員數量增大時會自動轉成真正的HashMap,此時encoding為ht。
更多Redis相關知識,請訪問Redis使用教程欄目!