前言
大家好,牧碼心今天給大家推薦一篇redis系列—數據結構之哈希(hash)的文章,在實際工作中有很多應用場景,希望對你有所幫助。內容如下:
- 特點
- 基本命令
- 時間複雜度
- 使用場景
特點
在Redis中, 哈希類型是指鍵值本身又是一個鍵值對結構, 形如value={{field1, value1}, …{fieldN, valueN}}, Redis鍵值對和哈希類型二者的關係可以用圖來表示:
基本命令
- 設置值
hset key field value
下面爲user: 1添加一對field-value:
127.0.0.1:6379> hset user:1 name tom
(integer) 1
如果設置成功會返回1, 反之會返回0。
- 獲取值
hget key field
下面操作獲取user: 1的name域(屬性) 對應的值:
127.0.0.1:6379> hget user:1 name
"tom"
如果鍵或field不存在, 會返回nil。
- 刪除field
hdel key field [field ...]
hdel會刪除一個或多個field, 返回結果爲成功刪除field的個數, 例如:
127.0.0.1:6379> hdel user:1 name
(integer) 1
- 批量設置或獲取field-value
hmget key field [field ...]
hmset key field value [field value ...]
hmset和hmget分別是批量設置和獲取field-value, hmset需要的參數是key
和多對field-value, hmget需要的參數是key和多個field。 例如:
127.0.0.1:6379> hmset user:1 name mike age 12 city tianjin
OK
127.0.0.1:6379> hmget user:1 name city
1) "mike"
2) "tianjin
- 判斷field是否存在
hexists key field
如 user:1包含name域, 所以返回結果爲1, 不包含時返回0:
127.0.0.1:6379> hexists user:1 name
(integer) 1
- 獲取所有field
hkeys key
- 獲取所有value
hvals key
- 獲取所有的field-value
hgetall key
下面操作獲取user: 1所有的field-value:
127.0.0.1:6379> hgetall user:1
1) "name"
2) "mike"
3) "age"
4) "12"
5) "city"
6) "tianjin"
在使用hgetall時, 如果哈希元素個數比較多, 會存在阻塞Redis的可能。
如果開發人員只需要獲取部分field, 可以使用hmget, 如果一定要獲取全部
field-value, 可以使用hscan命令, 該命令會漸進式遍歷哈希類型。
- 計算value的字符串長度(需要Redis3.2以上)
hstrlen key field
例如hget user:1 name的value是tom, 那麼hstrlen的返回結果是3。
127.0.0.1:6379> hstrlen user:1 name
(integer) 3
時間複雜度
下表哈希類型命令的時間複雜度,開發人員可以參考此表選擇適合的命令。
使用場景
假如用關係型數據表記錄的兩條用戶信息, 用戶的屬性作爲表的列,
每條用戶信息作爲行。如圖:
用哈希類型類型存儲,如圖:
相比於使用字符串序列化緩存用戶信息, 哈希類型變得更加直觀, 並且在更新操作上會更加便捷。可以將每個用戶的id定義爲鍵後綴, 多對fieldvalue對應每個用戶的屬性, 類似如下僞代碼:
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);
}r
eturn userInfo;
}
總之,使用哈希類型存儲,需要注意:
1、哈希類型是稀疏的, 而關係型數據庫是完全結構化的, 例如哈希類型
每個鍵可以有不同的field, 而關係型數據庫一旦添加新的列, 所有行都要爲
其設置值(即使爲NULL)
2、關係型數據庫可以做複雜的關係查詢, 而Redis去模擬關係型複雜查詢
開發困難, 維護成本高。