Hash类型
几乎所有的主流编程语⾔都提供了哈希(hash)类型,它们的叫法可能是哈希、字典、关联数组、映射。如果要存储一个人的姓名和年龄,可以使用string;类型,它们之间的映射关系如下:
而在 Redis 中,哈希类型是指值本身又是⼀个键值对结构,形如 key = "key",value = { {field1, value1 }, ..., {fieldN, valueN }}
,Redis 键值对和哈希类型⼆者的关系可以用下图所示:
就是原本的value里面有存储了新的哈希类型,Redis为了区分本身的key和value里面的key,所以把value里面的key新起了一个名称field。
设置与获取命令
HSET
Hset 命令用于为哈希表中的字段赋值 。如果哈希表不存在,一个新的哈希表被创建并进行 HSET 操作。如果字段已经存在于哈希表中,旧值将被覆盖。
语法:HSET key field value [field value ...]
示例:
127.0.0.1:6379> hset key1 hello 111
(integer) 1
127.0.0.1:6379> hget key1 hello
"111"
127.0.0.1:6379> hset key1 hello 222 // 旧值被覆盖,返回0
(integer) 0
127.0.0.1:6379> hget key1 hello
"222"
命令有效版本:2.0.0 之后。
时间复杂度:插⼊⼀组 field 为 O(1), 插⼊ N 组 field 为 O(N)。
返回值:添加的字段的个数。
HGET
Hget 命令用于返回哈希表中指定字段的值。
语法:HGET key field
示例:
127.0.0.1:6379> hset key1 hello 111
(integer) 1
127.0.0.1:6379> hget key1 hello
"111"
命令有效版本:2.0.0 之后。
时间复杂度:O(1)。
返回值:字段对应的值或者nil。
HEXISTS
Hexists 命令用于查看哈希表的指定字段是否存在。
语法:HEXISTS key field
示例:
127.0.0.1:6379> hexists key1 hello
(integer) 1
127.0.0.1:6379> hexists key1 test
(integer) 0
命令有效版本:2.0.0 之后。
时间复杂度:O(1)。
返回值:1 表示存在,0 表示不存在。
HDEL
Hdel 命令用于删除哈希表 key 中的一个或多个指定字段,不存在的字段将被忽略。
语法:HDEL KEY_NAME FIELD1.. FIELDN
示例:
127.0.0.1:6379> hset key2 world 222
(integer) 1
127.0.0.1:6379> hdel key2 world
(integer) 1
127.0.0.1:6379> hdel key2 hello
(integer) 0
命令有效版本:2.0.0 之后。
时间复杂度:删除⼀个元素为 O(1)。删除 N 个元素为 O(N)。
返回值:本次操作删除的字段个数。
HKEYS
Hkeys 命令用于获取哈希表中的所有域(field)。
语法:HKEYS key
示例:
127.0.0.1:6379> HSET myhash field1 "foo"
(integer) 1
127.0.0.1:6379> HSET myhash field2 "bar"
(integer) 1
127.0.0.1:6379> HKEYS myhash
1) "field1"
2) "field2"
命令有效版本:2.0.0 之后。
时间复杂度:O(N), N 为 field 的个数。
返回值:字段列表。
HVALS
Hvals 命令返回哈希表所有的值。
语法:HVALS key
示例:
127.0.0.1:6379> hset key1 test1 111 test2 222 test 333
(integer) 3
127.0.0.1:6379> hvals key1
1) "111"
2) "222"
3) "333"
命令有效版本:2.0.0 之后。
时间复杂度:O(N), N 为 field 的个数。
返回值:所有的值。
HGETALL
Hgetall 命令用于返回哈希表中,所有的字段和值。
在返回值里,紧跟每个字段名(field name)之后是字段的值(value),所以返回值的长度是哈希表大小的两倍。
语法:HGETALL key
示例:
127.0.0.1:6379> hgetall key1
1) "test1"
2) "111"
3) "test2"
4) "222"
5) "test"
6) "333"
命令有效版本:2.0.0 之后。
时间复杂度:O(N), N 为 field 的个数。
返回值:字段和对应的值。
HMGET
Hmget 命令用于返回哈希表中,一个或多个给定字段的值。如果指定的字段不存在于哈希表,那么返回一个 nil 值。
语法:HMGET KEY_NAME FIELD1...FIELDN
示例:
127.0.0.1:6379> hmget key1 test1 test2
1) "111"
2) "222"
127.0.0.1:6379> hmget key1 test1 test2 test4
1) "111"
2) "222"
3) (nil)
命令有效版本:2.0.0 之后。
时间复杂度:只查询⼀个元素为 O(1), 查询多个元素为 O(N), N 为查询元素个数。
返回值:字段对应的值或者 nil。
HMSET
Hmset 命令用于同时将多个 field-value (字段-值)对设置到哈希表中。此命令会覆盖哈希表中已存在的字段。如果哈希表不存在,会创建一个空哈希表,并执行 HMSET 操作。
语法:HMSET KEY_NAME FIELD1 VALUE1 ...FIELDN VALUEN
示例:
127.0.0.1:6379> hmset key2 test1 111 test2 222 test3 333
OK
127.0.0.1:6379> hget key2 test2
"222"
127.0.0.1:6379> hget key2 test3
"333"
命令有效版本:2.0.0之后。
返回值:如果命令执行成功,返回OK。
HLEN
Hlen 命令用于获取哈希表中字段的数量。
语法:HLEN KEY_NAME
示例:
127.0.0.1:6379> hlen key1
(integer) 3
命令有效版本:2.0.0 之后。
时间复杂度:O(1)。
返回值:字段个数。
HSETNX
Hsetnx 命令用于为哈希表中不存在的的字段赋值 。
如果哈希表不存在,一个新的哈希表被创建并进行 HSET 操作。
如果字段已经存在于哈希表中,操作无效。
如果 key 不存在,一个新哈希表被创建并执行 HSETNX 命令。
语法:HSETNX KEY_NAME FIELD VALUE
示例:
127.0.0.1:6379> HSETNX myhash field1 "foo"
(integer) 1
127.0.0.1:6379> HSETNX myhash field1 "bar"
(integer) 0
127.0.0.1:6379> HGET myhash field1
"foo"127.0.0.1:6379> HSETNX nosql key-value-store redis
(integer) 1127.0.0.1:6379> HSETNX nosql key-value-store redis # 操作无效, key-value-store 已存在
(integer) 0
命令有效版本:2.0.0 之后。
时间复杂度:O(1)。
返回值:1 表⽰设置成功,0 表⽰失败。
HINCRBY
将 hash 中字段对应的数值添加指定的值。增量也可以为负数,相当于对指定字段进行减法操作。
语法:HINCRBY KEY_NAME FIELD_NAME INCR_BY_NUMBER
示例:
127.0.0.1:6379> hget key1 test1
"111"
127.0.0.1:6379> hincrby key1 test1 5
(integer) 116
127.0.0.1:6379> hincrby key1 test1 -10
(integer) 106
命令有效版本:2.0.0 之后。
时间复杂度:O(1)。
返回值:该字段变化之后的值。
HINCRBYFLOAT
Hincrbyfloat 命令用于为哈希表中的字段值加上指定浮点数增量值。如果指定的字段不存在,那么在执行命令前,字段的值被初始化为 0 。
语法:key field increment
示例:
127.0.0.1:6379> hincrby key1 test1 -10
(integer) 106
127.0.0.1:6379> hincrbyfloat key1 test1 1.5
"107.5"
127.0.0.1:6379> hincrbyfloat key1 test1 -1.5
"106"
命令有效版本:2.6.0 之后。
时间复杂度:O(1)。
返回值:该字段变化之后的值。
应用场景
最常见的应用场景就是购物车里,以用户 id 为key,商品id为 field,商品数量为 value,恰好构成了购物车的三个要素,如下图所示:
涉及到命令如下:
- 添加商品:
HSET cart:{用户id} {商品id} 1
- 添加数量:
HINCRBY cart:{用户id} {商品id} 1
- 商品总数:
HLEN cart:{用户id}
- 删除商品:
HDEL cart:{用户id} {商品id}
- 获取购物车所有商品:
HEGTALL cart:{用户id}
当前仅仅是将商品id存储到了Redis中,在回显商品具体信息到时候,还需要拿着商品id查询一次数据库,获取完整的商品的信息。