【redis】数据类型之hash

Redis中的Hash数据类型是一种用于存储键值对集合的数据结构。与Redis的String类型不同,Hash类型允许你将多个字段(field)和值(value)存储在一个单独的key下,从而避免了将多个相关数据存储为多个独立的key。这样做的好处是减少了key的数量,使得数据的管理和操作更加高效。

hash这个数据类型类似java中的HashMap,都由key-value键值对组成。

有关hash类型的命令可以通过help @hash命令来查看。有关命令的使用可以通过help 命令来查看,例如help hset

HSET

hset:设置hash指定字段的值。

语法:

shell 复制代码
HSET key field value [field value ...]

使用:

shell 复制代码
127.0.0.1:6379> hset h1 name morris age 18
(integer) 2

HGET

hget:获取hash指定字段的值。

语法:

shell 复制代码
HGET key field

使用:

shell 复制代码
127.0.0.1:6379> hget h1 name
"morris"

HKEYS

hkeys:获取hash所有的字段。

语法:

shell 复制代码
HKEYS key

使用:

shell 复制代码
127.0.0.1:6379> hkeys h1
1) "name"
2) "age"

HVALS

hvals:获取hash所有的值。

语法:

shell 复制代码
HVALS key

使用:

shell 复制代码
127.0.0.1:6379> hvals h1
1) "morris"
2) "18"

HGETALL

hgetall:获取hash所有的字段和值。

语法:

shell 复制代码
HGETALL key

使用:

shell 复制代码
127.0.0.1:6379> hgetall h1
1) "name"
2) "morris"
3) "age"
4) "18"

HEXISTS

hexists:判断hash中某个字段是否存在。

语法:

shell 复制代码
HEXISTS key field

使用:

shell 复制代码
127.0.0.1:6379> hexists h1 name
(integer) 1

HLEN

hlen:返回hash中键值对的个数。

语法:

shell 复制代码
HLEN key

使用:

shell 复制代码
127.0.0.1:6379> hlen h1
(integer) 2

HINCRBY

hincrby:给hash中指定字段的值增加一个整型。

语法:

shell 复制代码
INCRBY key increment

使用:

shell 复制代码
127.0.0.1:6379> hincrby h1 age 1
(integer) 19

HINCRBYFLOAT

hincrbyfloat:给hash中指定字段的值增加一个浮点型。

语法:

shell 复制代码
INCRBYFLOAT key increment

使用:

shell 复制代码
127.0.0.1:6379> hincrbyfloat h1 age 0.5
"19.5"

HSTRLEN

hstrlen:获取hash指定字段的值的长度。

语法:

shell 复制代码
HSTRLEN key field

使用:

shell 复制代码
127.0.0.1:6379> hstrlen h1 name
(integer) 6

HMSET

hmset:批量设置hash,这个跟hset命令一样了,只是hset只支持设置一个,能保证原子性。

语法:

shell 复制代码
HMSET key field value [field value ...]

使用:

shell 复制代码
127.0.0.1:6379> hmset k k1 v1 k2 v2 k3 v3
OK

127.0.0.1:6379> hgetall k
1) "k1"
2) "v1"
3) "k2"
4) "v2"
5) "k3"
6) "v3"

HMGET

hmget:批量获取hash的字段对应的值。

语法:

shell 复制代码
HMGET key field [field ...]

使用:

shell 复制代码
127.0.0.1:6379> hmget k k1 k2 k3
1) "v1"
2) "v2"
3) "v3"

HSETNX

hsetnx:字段不存在则设置成功,类似setnx命令,只能设置一个字段。

语法:

shell 复制代码
HSETNX key field value

使用:

shell 复制代码
127.0.0.1:6379> hsetnx kk name bob
(integer) 1

HDEL

hdel:删除字段。

语法:

shell 复制代码
HDEL key field [field ...]

使用:

shell 复制代码
127.0.0.1:6379> hdel k k1
(integer) 1

127.0.0.1:6379> hkeys k
1) "k2"
2) "k3"

HRANDFIELD

hrandfield:用于随机返回一个或多个存储在指定key中的哈希表(hash)里字段的值。

语法:

shell 复制代码
HRANDFIELD key [count [WITHVALUES]]

使用:

shell 复制代码
127.0.0.1:6379> hrandfield h1 1 withvalues
1) "age"
2) "18"

HSCAN

hscan:用于迭代哈希表(Hashes)中键值对的命令,有点类似于SCAN。

语法:

shell 复制代码
HSCAN key cursor [MATCH pattern] [COUNT count]

使用:

shell 复制代码
127.0.0.1:6379> hscan h1 0 MATCH a* COUNT 1
1) "0"
2) 1) "age"
   2) "18"

内部编码

哈希类型的内部编码有两种:

  • ziplist(压缩列表):当哈希类型元素个数小于hash-max-ziplist-entries配置(默认512个)、同时所有值都小于hash-max-ziplist-value配置(默认64字节)时,Redis会使用ziplist作为哈希的内部实现,ziplist使用更加紧凑的结构实现多个元素的连续存储,所以在节省内存方面比hashtable更加优秀。

  • hashtable(哈希表):当哈希类型无法满足ziplist的条件时,Redis会使用hashtable作为哈希的内部实现,因为此时ziplist的读写效率会下降,而hashtable的读写时间复杂度为O(1)。

shell 复制代码
127.0.0.1:6379> object encoding h1
"ziplist"

127.0.0.1:6379> hset y str "one string is bigger than 64 byte...............one string is bigger than 64 byte..............."
(integer) 1

127.0.0.1:6379> object encoding y
"hashtable"

使用场景

hash常用来存储关系型数据库中的记录。

假设现在数据库有一张user表,如下:

下面给出三种方案来缓存用户信息。

  1. 使用原生字符串类型存储,每个属性一个键。
shell 复制代码
127.0.0.1:6379> mset user:1:name morris user:1:age 18 user:1:city beijing
OK

127.0.0.1:6379> mset user:2:name bob user:1:age 20 user:1:city hongkong
OK

127.0.0.1:6379> keys user:1:*
1) "user:1:age"
2) "user:1:name"
3) "user:1:city"

127.0.0.1:6379> mget user:1:name user:1:age user:1:city
1) "morris"
2) "20"
3) "hongkong"

优点:简单直观,每个属性都支持更新操作。

缺点:占用过多的键,内存占用量较大,同时用户信息内聚性比较差。

  1. 将数据库中的一行记录序列化为json,用一个key保存。
shell 复制代码
127.0.0.1:6379> set user:1 '{"id":1,"name":"morris","age":18,"city":"beijing"}'
OK

127.0.0.1:6379> get user:1
"{"id":1,"name":"morris","age":18,"city":"beijing"}"

127.0.0.1:6379> set user:2 '{"id":2,"name":"bob","age":20,"city":"hongkong"}'
OK

127.0.0.1:6379> get user:2
"{"id":2,"name":"bob","age":20,"city":"hongkong"}"

优点:简化编程,如果合理的使用序列化可以提高内存的使用效率。

缺点:序列化和反序列化有一定的开销,同时每次更新属性都需要把全部数据取出进行反序列化,更新后再序列化到Redis中。

  1. 使用hash存储,每行记录的一列对应一个field-value。
shell 复制代码
127.0.0.1:6379> hset user:1 name morris age 18 city beijing
(integer) 3

127.0.0.1:6379> hset user:2 name bob age 20 city hongkong
(integer) 3

127.0.0.1:6379> hgetall user:1
1) "name"
2) "morris"
3) "age"
4) "18"
5) "city"
6) "beijing"

127.0.0.1:6379> hgetall user:2
1) "name"
2) "bob"
3) "age"
4) "20"
5) "city"
6) "hongkong"

优点:简单直观,如果使用合理可以减少内存空间的使用。

缺点:要控制哈希在ziplist和hashtable两种内部编码的转换,hashtable会消耗更多内存。

相关推荐
IvorySQL1 小时前
PostgreSQL 分区表的 ALTER TABLE 语句执行机制解析
数据库·postgresql·开源
·云扬·1 小时前
MySQL 8.0 Redo Log 归档与禁用实战指南
android·数据库·mysql
IT邦德1 小时前
Oracle 26ai DataGuard 搭建(RAC到单机)
数据库·oracle
惊讶的猫2 小时前
redis分片集群
数据库·redis·缓存·分片集群·海量数据存储·高并发写
不爱缺氧i2 小时前
完全卸载MariaDB
数据库·mariadb
期待のcode2 小时前
Redis的主从复制与集群
运维·服务器·redis
纤纡.2 小时前
Linux中SQL 从基础到进阶:五大分类详解与表结构操作(ALTER/DROP)全攻略
linux·数据库·sql
jiunian_cn2 小时前
【Redis】渐进式遍历
数据库·redis·缓存
橙露2 小时前
Spring Boot 核心原理:自动配置机制与自定义 Starter 开发
java·数据库·spring boot
冰暮流星2 小时前
sql语言之分组语句group by
java·数据库·sql