【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会消耗更多内存。

相关推荐
你好龙卷风!!!6 小时前
mac m4 Homebrew安装MySQL 8.0
数据库·mysql·macos
binnnngo6 小时前
Spring Boot集成阿里云OSS:对象存储实战指南
数据库·spring boot·阿里云
程序猿ZhangSir6 小时前
Redis 和 MySQL双写一致性的更新策略有哪些?常见面试题深度解答。
java·数据库·spring boot·redis·mysql·缓存·mybatis
microhex6 小时前
一文了解Gradle 依赖管理(五)- 依赖管理&缓存依赖
缓存·gradle·maven
StarRocks_labs7 小时前
【活动回顾】StarRocks Singapore Meetup #2 @Shopee
数据库·starrocks·数据分析·spark·olap·物化视图·apache druid
逍遥德7 小时前
【数据库事务、消息队列事务、Redis 事务、Spring 事务 详细分析】
数据库·redis·spring·rabbitmq·rocketmq
nbsaas-boot8 小时前
SQL Server 动态构建 SQL 语句学习指南
数据库·sql
HongXuan-Yuan9 小时前
Spring Boot框架
java·数据库·spring boot
明月看潮生9 小时前
青少年编程与数学 02-012 SQLite 数据库简介 01课题、数据库概要
数据库·青少年编程·sqlite·编程与数学
码代码的小农10 小时前
MySQL中如何进行SQL调优?
数据库·sql·mysql