在Redis中,哈希类型是指值本身有是一个键值对结构,形如:
key = "key",
value = {{field1, value1}, {field2, value2}}
{: height=75%, width=75%}
注意:哈希类型中的映射关系通常为field-value,用于区分Redis整体的键值对(key-value),注意的是这里的value是指field对应的值,不是键(key)对应的值。
HSET
功能:设置hash中指定的字段(field)和值(value)
时间复杂度:$O(1)$
返回值:添加的字段的个数
HSET key field value [field value..]
127.0.0.1:6379> hset key f1 111
(integer) 1
127.0.0.1:6379> hset key f2 222 f3 333 f4 444
(integer) 3
HGET
功能:获取hash中指定的字段的值(value)
时间复杂度:$O(1)$
返回值:值
HSET key field
127.0.0.1:6379> hget key f1
"111"
127.0.0.1:6379> hget key f2
"222"
HEXISTS
功能:判断hash中是否有指定字段
时间复杂度:$O(1)$
返回:是否存在
HEXISTS key field
127.0.0.1:6379> hexists key f1
(integer) 1
127.0.0.1:6379> hexists key f2
(integer) 1
127.0.0.1:6379> hexists key f10
(integer) 0
HDEL
功能:删除hash中的指定字段
时间复杂度:$O(1)$
返回值:本次操作删除字段的个数
HDEL key field
127.0.0.1:6379> hdel key f4
(integer) 1
DEL
功能:删除key,删除key所对应的哈希表
DEL key
127.0.0.1:6379> del key
(integer) 1
HKEYS
功能:获取hash中所有的字段,会根据key找到对应的hash,然后再遍历hash
时间复杂度:$O(N)$,N表示key对应hash表中键值对的数目
HKEYS key
127.0.0.1:6379> hset key f1 111 f2 222 f3 333 f4 444
(integer) 4
127.0.0.1:6379> hkeys key
1) "f1"
2) "f2"
3) "f3"
4) "f4"
HVALUES
功能:能够获取到hash中所有的value
HVALS key
127.0.0.1:6379> hvals key
1) "111"
2) "222"
3) "333"
4) "444"
HGETALL
功能:获取hash中的所有字段以及对应的值。
HGETALL key
127.0.0.1:6379> hgetall key
1) "f1"
2) "111"
3) "f2"
4) "222"
5) "f3"
6) "333"
7) "f4"
8) "444"
HMGET
功能:一次查询多个field
,可以减少网络通讯带来的开销
127.0.0.1:6379> hmget key f1 f2 f3
1) "342"
2) "222"
3) "333"
HMSET
功能:一次设置多个field-value
键值对,可以减少网络通讯带来的开销。
127.0.0.1:6379> hmset key f1 f2 f3
127.0.0.1:6379> hmset key f5 555 f6 666
OK
127.0.0.1:6379> hgetall key
1) "f1"
2) "342"
3) "f2"
4) "222"
5) "f3"
6) "333"
7) "f4"
8) "444"
9) "f5"
10) "555"
11) "f6"
12) "666"
HSCAN
功能:遍历redis
的hash
,但是它属于渐进式遍历。敲一次命令,遍历一小部分,再敲一次,再遍历一小部分。执行多次就可以完成整个的遍历过程。
HSCAN key cursor [MATCH pattern] [COUNT count]
参数:
key
:哈希表的键。cursor
:迭代器的游标,初始值为0
,表示迭代开始。每次HSCAN
命令执行后,都会返回一个新的游标值,用于下一次迭代。MATCH pattern
(可选):指定一个模式,只有符合模式的字段才会被返回。COUNT count
(可选):指定每次迭代返回的最大元素数量。返回值:HSCAN
命令返回两个值:
0
,表示迭代完成。127.0.0.1:6379> hscan key 0
1) "0"
2) 1) "f1"
1) "111"
2) "f2"
3) "222"
4) "f3"
5) "333"
6) "f4"
7) "444"
HLEN
时间复杂度:$O(1)$
功能:获取Hash
的个数
HLEN key
127.0.0.1:6379> hlen key
(integer) 4
HSETNX
功能:设置哈希表键值对,对于不存在的键值对,才能设置成功
时间复杂度:$O(1)$
HSETNX key filed value
127.0.0.1:6379> hsetnx key f5 555
(integer) 1
127.0.0.1:6379> hsetnx key f1 111
(integer) 0
HINCRBY
功能:将hash
中字段对应的数值添加指定的值。hash
这里的value
,也可以当做数组处理。hincrby
就可以加减整数,hincrbyfloat
就可以加减小数。
127.0.0.1:6379> hincrby key f1 231
(integer) 342
127.0.0.1:6379> hgetall key
1) "f1"
2) "342"
3) "f2"
4) "222"
5) "f3"
6) "333"
7) "f4"
8) "444"
命令 | 执行效果 | 时间复杂度 |
---|---|---|
hset key field value | 设置值 | O(1) |
hget key field | 获取值 | O(1) |
hset key field [field....] | 删除field | O(k) |
hlen key | 计算field个数 | O(1) |
hgetall key | 获取所有的field-value | O(k) |
hmget field [field...] | 批量获取field-value | O(k) |
hmget key field value [field value...] | 批量获取filed-value | O(k) |
hexists key field | 判断field是否存在 | O(1) |
hkeys key | 获取所有的field | O(k) |
hvals key | 获取所有的value | O(k) |
hkeys key | 获取所有的field | O(k) |
hsetnx key field value | 设置值,但必须在field不存在时才能设置成功 | O(1) |
hincrby key field n | 对于filed-value + n | O(1) |
hincrbyfloat key field n | 对于filed-value + n | O(1) |
hstrlen key field n | 计算value的字符串长度 | O(1) |
哈希的内部编码有两种
ziplist
(压缩列表):当哈希类型元素个数小于hash-max-ziplst-entries
配置(默认512个),同时所有值都小于hash-max-ziplist-value
配置(默认64字节)时,Redis
会使用ziplist
作为哈希的内部实现,ziplist
使用更加紧凑的结构实现多个元素的连续存储,所以在节省内存方面比hashtable
更加优秀。hashtable
(哈希表):当哈希类型无法满足ziplist
的条件时,Redis
会使用hashtable
作为哈希的内部实现,因此此时ziplist
的读写效率会下降,而hashtable
的读写时间复杂度为$O(1)$ziplist
表示,元素个数较多,使用hashtable
表示value
的值长度都比较短,使用ziplist
表示,如果某个value
的长度太长了,也会转换成hashtable
127.0.0.1:6379> hset key f1 111
(integer) 1
127.0.0.1:6379> object encoding key
"ziplist"
127.0.0.1:6379> hset key f2 222222.....22222222222222222222222222222222222222222
(integer) 1
127.0.0.1:6379> object encoding key
"hashtable"
下图为关系型数据表记录的两条用户信息,用户的属性表现为表的列,每条用户信息表现为行。
{: height=75%, width=75%}
下图为映射关系表示这两个用户信息。
{: height=75%, width=75%}
上述场景string类型也可以做到,就需要用到json这样的数据格式。但是我们只是想要里面的某一个field,或者修改某个field。就需要把整个json都读出来,解析成对象,操作field,再重写转成json字符串,再写回去。
如果使用hash
方式表示Userinfo
,就可以使用field表示对象的某个属性,此时就可以非常方便的修改/获取任何一个属性的值了。此方式确实读写field
更直观高效,但是要付出空间代价。需要控制哈希在ziplist
和hashtable
两种内部编码的转换,可能会造成内存的较大消耗。
原生字符串类型
set user:1:name James
set user:1:age 23
set user:1:city Beijing
序列化字符串类型
set user:1 经过序列化后的用户对象字符串
哈希类型
hmset user:1 name James age 23 city Beijing