title: 哈希表hash
categories:
- C++ Backend
- Redis
- Redis command
- Data structure
tags:
- Redis
date: 2025-04-03 00:00:00
cover: /images/Redis.png

hash

概述

在Redis中,哈希类型是指值本身有是一个键值对结构,形如:

key = "key",
value = {{field1, value1}, {field2, value2}}   

alt text{: 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

功能:遍历redishash,但是它属于渐进式遍历。敲一次命令,遍历一小部分,再敲一次,再遍历一小部分。执行多次就可以完成整个的遍历过程。

HSCAN key cursor [MATCH pattern] [COUNT count]

参数:

返回值:HSCAN命令返回两个值:

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)

内部编码

哈希的内部编码有两种

  1. 如果是哈希中的元素个数较少,使用ziplist表示,元素个数较多,使用hashtable表示
  2. 每个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"

使用场景

缓存

下图为关系型数据表记录的两条用户信息,用户的属性表现为表的列,每条用户信息表现为行。

alt text{: height=75%, width=75%}

下图为映射关系表示这两个用户信息。

alt text{: height=75%, width=75%}

上述场景string类型也可以做到,就需要用到json这样的数据格式。但是我们只是想要里面的某一个field,或者修改某个field。就需要把整个json都读出来,解析成对象,操作field,再重写转成json字符串,再写回去。

如果使用hash方式表示Userinfo,就可以使用field表示对象的某个属性,此时就可以非常方便的修改/获取任何一个属性的值了。此方式确实读写field更直观高效,但是要付出空间代价。需要控制哈希在ziplisthashtable两种内部编码的转换,可能会造成内存的较大消耗。

原生字符串类型

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