前言
簡單介紹一下哈希基本結構和命令。
正文
什麼是hash呢? hash也可以叫做字典、關聯數組。
哈希類型是鍵本身又是一個鍵值對結構:
value={{field1,value1},...{fieldN,valueN}}
哈希類型中的映射關系叫作field-value,注意這裏的value是指field對應 的值,不是鍵對應的值,請注意value在不同上下文的作用。
來看下命令。
hset key field value
獲取值:
hget user:1 name
删除:
hdel key field [field ...]
判斷有多少值:
一次性獲取多個值:
同樣有mset:
然後還可以判斷field 是否存在。
hexists key field
獲取其全部的key:
獲取其全部的值:
獲取全部的keyvalue:
在使用hgetall時,如果哈希元素個數比較多,會存在阻塞Redis的可能。 如果開發人員只需要獲取部分field,可以使用hmget,如果一定要獲取全部 field-value,可以使用hscan命令,該命令會漸進式遍曆哈希類型。
hincrby key field
hincrbyfloat key field
hincrby和hincrbyfloat,就像incrby和incrbyfloat命令一樣,但是它們的作 用域是filed。
計算value的字符串長度
hstrlen key field
哈希命令複雜度:
內部編碼:
·ziplist(壓縮列錶):當哈希類型元素個數小於hash-max-ziplist-entries 配置(默認512個)、同時所有值都小於hash-max-ziplist-value配置(默認64 字節)時,
Redis會使用ziplist作為哈希的內部實現,ziplist使用更加緊凑的 結構實現多個元素的連續存儲,所以在節省內存方面比hashtable更加優秀。
·hashtable(哈希錶):當哈希類型無法滿足ziplist的條件時,Redis會使 用hashtable作為哈希的內部實現,因為此時ziplist的讀寫效率會下降,而 hashtable的讀寫時間複雜度為O(1)。
使用場景:
- 緩存,比如用作用戶信息存儲
前面提及到用戶信息用字符串存儲,然後再系列化。
相比於使用字符串序列化緩存用戶信息,哈希類型變得更加直觀,並且 102
在更新操作上會更加便捷。可以將每個用戶的id定義為鍵後綴,多對field- value對應每個用戶的屬性,類似如下偽代碼:
UserInfo getUserInfo(long id){ // 用戶id作為key後綴 userRedisKey = "user:info:" + id; /
/ 使用hgetall獲取所有用戶信息映射關系 userInfoMap = redis.hgetAll(userRedisKey);
UserInfo userInfo; if (userInfoMap != null) { // 將映射關系轉換為UserInfo userInfo = transferMapToUserInfo(userInfoMap); }
else { // 從MySQL中獲取用戶信息 userInfo = mysql.get(id); // 將userInfo變為映射關系使用hmset保存到Redis中 redis.hmset(userRedisKey, transferUserInfoToMap(userInfo));
// 添加過期時間 redis.expire(userRedisKey, 3600); }return userInfo; }
這樣相比於字符串呢,每次就不用去系列化了,字符串每次都要去進行系列化,然後反系列化存儲,具備一定的開銷。
然後哈希類型當然也是有缺點的,如果編碼是hashtable,那麼是比較消耗內存的。
結
下一節redis的list 整理。