本篇文章帶大家了解一下redis中的hash數據類型,介紹一下hash 類型數據的基本操作,希望對大家有所幫助!
1. hash類型數據概述
我們先來看這個例子
在上一節我們一起了解了 string 存儲類型。但是如果是對象數據的存儲具有較頻繁的更新需求,操作會顯得笨重。例如:user:id:100 -> {“id”:100,”name”:”春晚”,”fans”:12355,”blogs”:99,”focus:83},如果需要更新一個對象中的局部數據,就需要替換掉所有數據,于是有了以下的需求。【相關推薦:Redis視頻教程】
新的需求:對一系列存儲的數據進行編組,方便管理,比如存儲一個對象的信息需要的存儲結構:一個存儲空間保存多個鍵值對數據
如下圖:
為了解決這個問題,我們引入新的數據類型:hash。同時 hash 存儲結構也做了以下優化
- 如果 field 數量較小,存儲結構優化為類數組結構
- 如果 field 數量較多,存儲結構使用 HashMap 結構
2. hash 類型數據的基本操作
- 修改/添加數據
hset?key?field?value
- 查詢單個字段/查詢所有字段
#?查詢單個字段數據 hget?key?field #?查詢所有數據 hgetall?key
- 刪除操作
hdel?key?field1?[field2]
- 修改/添加多個數據
hmset?key?field1?value1?field2?value2
- 返回 hash 表中,一個或多個給定字段的值
hmget?key?field1?field2
- 獲取 hash 表中字段的數量
hlen?key
- 獲取 hash 表中是否存在指定的字段
hexists?key?field
3. hash 類型數據的擴展操作
- 獲取 hash 表中所有字段名或字段值
hkey?key hvals?key
- 設置指定字符段的數值數據增加指定范圍的值
hincrby?key?field?increment hincrbyfloat?key?field?increment
hash 類型數據操作注意事項
-
hash 類型下的 value 只能存儲字符串,不允許存儲其他數據類型,不存在嵌套對象。如果數據未獲取到,對應的結果為(nil);
-
每個 hash 可以存儲 2 的 32 次方減 1 個鍵值對;
-
hash 類型十分貼近對象的數據存儲形式,并且可以靈活添加刪除對象屬性,但 hash 設計初衷不是為了存儲大量對象而設計,切記不可濫用,更不可以將 hash 作為對象列表使用;
-
hgetall 操作可以獲取全部屬性,如果內部 field 過多,遍歷整個數據效率會很低,有可能成為數據訪問瓶頸。
4. hash的應用案例
4.1. 用hash實現購物車
概述
在這里我們不討論購物車與數據庫間的持久化同步,也不討論購物車與訂單之間的關系,同時忽略未登錄用戶購物車信息存儲。我們僅僅用 redis 的存儲模型來 對購物車 的條目進行 添加、瀏覽、更改數量、刪除、清空
實現方案
- 以客戶 id 作為 key,每位用戶創建一個 hash 存儲結構對應購物車信息
- 將商品編號作為 field,購買數量作為 value 進行存儲
- 添加商品:追加全新的 field 與 value
- 瀏覽商品:遍歷 hash
- 更改數量:自增/自減,設置 value 值
- 刪除商品:刪除 field
- 清空:刪除 key
示例代碼如下:
#?001?用戶購買?ID為101商品?100件,ID為102的商品?200件 hmset?001?101?100?102?200 #?002?用戶購買?ID為102商品?1件,ID為104的商品?7件 hmset?002?102?1?104?7
商品信息加速
當前僅僅是將數量存儲到 redis 中,并沒有起到加速作用,因為商品信息還需要查詢數據庫。可以使用以下方案解決:
每條購物車中的商品信息記錄保存為兩個 field
- field1 專門用于保存數量
命名格式:商品 id:nums 保存數據:數值
- field2 專門用于保存購物車中顯示的商品信息,包含文字描述,圖片地址,所屬商家信息等
命名格式:商品 id:info 保存數據:json
示例代碼如下:
#?001?用戶?購買?ID為101的商品?2件,商品的信息為:{"name":"good?name"}? hmset?001?101:num?2??101:info?"{"name":"goods?name"}" #?002?用戶?購買?ID為101的商品?1件,商品的信息為:{"name":"good?name"}? hmset?002?101:num?1??101:info?"{"name":"goods?name"}"
在上面的101:info 對應的值中,字符串包含了空格,所以用雙引號引用起來,達到轉義的目的。
商品信息獨立保存
由于 field2 可能在多條商品記錄中存在,因此 field2 里的數據可保存到獨立的 hash。此時,如果每添加一條購物車記錄,就保存一次 hash 數據,顯然是不合理的,可以通過hsetnx操作來保存數據,如果數據存在,則不執行保存操作。
命令格式如下
hsetnx?key?field?value
代碼示例如下
#?將id為101?的商品獨立存起來 hsetnx?info?101?"{"name":"goods?name"}"
4.1. 用hash實現搶購
案例:雙 11 活動日,銷售手機充值卡的商家對移動、聯通、電信的 30 元、50 元、100 元商品推出搶購活動,每種商品的搶購上限為 100。
解決方案
- 以商家 id 作為 key
- 將參與搶購的商品作為 field
- 將參與搶購的商品數量作為對應的 value
- 搶購時使用降值的方式控制產品數量
- 實際業務中還有超賣等實際問題,這里不做討論
實現過程
商品初始信息
#?p01商家下,c30充值券1000張,c50充值券1000張,c100充值券1000張 hmset?p01?c30?1000?c50?1000?c100?1000
當 c30 售出1件時,值減 1; 當 c100 售出 20 件時,值減 20,如下代碼
#?p01商家,商品c30售出1件 hincrby?p01?c30?-1 #?p01商家,商品c100售出20件 hincrby?p01?c100?-20
5. string 存對象對比 hash 存對象
-
string 存儲 json 字符串:讀取方便,在更新的時候會整體進行更新
-
hash 存對象具體的字段:更新靈活
引入 hash 數據類型之后,我們就解決了 string 存儲對象,更新對象時需要整體更新的問題。
更多編程相關知識,請訪問:Redis視頻教程!!