Redis Hash(Hash) 复习

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 哈希相当于一个二维数组,内部是无序字典。哈希也是是一个 string 类型的 field(字段) 和 value(值) 的映射表,所以哈希特别适合用于存储对象。

介绍

哈希相当于一个二维数组,内部是无序字典。

哈希也是是一个 string 类型的 field(字段) 和 value(值) 的映射表,所以哈希特别适合用于存储对象。

应用场景

Hash也可以同于对象存储,比如存储用户信息,与字符串不一样的是,字符串是需要将对象进行序列化(比如json序列化)之后才能保存,而Hash则可以讲用户对象的每个字段单独存储,这样就能节省序列化和反序列的时间。如下:

此外还可以保存用户的购买记录,比如key为用户id ,field为商品id,value为商品数量。同样还可以用于购物车数据的存储,比如key为用户id,field为商品id,value为购买数量等等。

数据结构

哈希是数组 + 链表二维结构。第一维 hash 的数组位置碰撞时,就会将碰撞的元素使用链表串接起来。

新增(HSET、HMSET)

HSET(推荐)

# HSET key field value [field value ...]
# key 名称 field 第二维数组索引 
# 如果哈希表不存在,则创建,存在即覆盖
# 新建字段,设置成功,返回 1 。 存在且旧值已被覆盖,返回 0 
> HSET myhash 1 zhangsan 2 lisi 3 wangwu
(integer) 3

不存在时创建(HSETNX)

# 成功,返回 1 。 字段存在,返回 0 
# HSETNX key field value
> HSETNX myhash2 1 zhansi
(integer) 1

HSETNX 只能创建单个key-value

HMSET(4.0后已遗弃)

# HMSET key field value [field value ...]
# key 名称 field 第二维数组索引 vakue值 
# 如果哈希表不存在,则创建,存在即覆盖
# 执行成功,返回 OK 。 
> HMSET myhash1 1 zhangsan 2 lisi 3 wangwu
OK

注意:HMSET无法覆盖旧值,当旧值存在会执行失败

根据Redis 4.0.0,HMSET被视为已弃用。请在新代码中使用HSET。

查询

查看单值 (HGET)

# 获取指定的值
# HGET key field
# 返回给定字段的值。不存在时,返回 nil 
> HGET myhash 1
"zhangsan2"

获取给定字段多值(HMGET)

# 返回给定字段值,不存在返回nil
# HMGET key field [field ...]
> HMGET myhash 1 2 3 4
1) "zhangsan2"
2) "lisi"
3) "wangwu1"
4) (nil)

获取所有的字段和值(HGETALL)

# 获取所有的字段和值
# 返回字段及字段值。不存在,返回空列表
# HGETALL key
> HGETALL myhash
1) "1"
2) "zhangsan2"
3) "2"
4) "lisi"
5) "3"
6) "wangwu1"

获取所有的Key(HKEYS)

# 获取所有的字段和值
# 返回域(field)列表。不存在,返回空列表
# HKEYS key
> HKEYS myhash
1) "1"
2) "2"
3) "3"

获取所有的值(HVALS)

# 所有值的列表。 不存在时,返回空列表。
# HVALS key
> HVALS myhash1
1) "zhangsan"
2) "lisi"
3) "wangwu"

统计字段数量(HLEN)

# 返回字段的数量。不存在时,返回 0
# HLEN key
> HLEN myhash1
(integer) 3

其他操作

判断字段是否存在(HEXISTS)

# 存在,返回 1 ,不存在,返回 0 
# HEXISTS key field
> HEXISTS myhash 1
(integer) 1

HEXISTS 可以判断 field 也可以判断 key

自增给定增量(HINCRBY)

# increment增量
# 返回当前字段的值
# HINCRBY key field increment
> hset myhash1 5 5
(integer) 1
> HINCRBY myhash1 5 2
(integer) 7

increment增量可以为负数

自增给定浮点增量(HINCRBYFLOAT)

# increment增量
# 返回当前字段的值
# HINCRBYFLOAT key field increment
> HINCRBYFLOAT myhash1 5 3.5
"10.5"

increment浮点增量可以为负数

迭代(HSCAN)

HSCANSCAN 类似,HSCAN 针对于hash中的field值,而SCAN针对于redis中所有的key值;

HSCAN key cursor [MATCH pattern] [COUNT count]
MATCH 正则匹配模式
COUNT limit 遍历的条数


重点注意:HSCAN 命令是一个迭代器,是一个迭代器,是一个迭代器!

因为是迭代器,所以每次被调用都需要使用上一次这个调用返回的游标作为该次调用的游标参数,以此来延续之前的迭代过程, 当SCAN命令的游标参数被设置为 0 时, 服务器将开始一次新的迭代, 而当服务器向用户返回值为 0 的游标时, 表示迭代已结束。

讲人话就是 HSCAN 命令返回不是全部元素,需要跟着游标多次迭代才能得到所有的结果。

Redis 6.0 以上版本中 SCAN COUNT参数需要多次迭代遍历,而HSCAN COUNT 不需要多次迭代遍历,只需要设置迭代次数则可以全部迭代

SCAN COUNT 需要如下遍历

遍历结果如:

  • 第一次遍历时,cursor值为0
  • 将返回结果中第一个整数值作为下一次遍历的cursor
  • 一直遍历到返回的cursor的值为0时结束。

SCAN与HSCAN对比

利用Php插入10000条数据

require_once __DIR__ . '/../vendor/autoload.php';
$client = new Predis\Client([
    'scheme' => 'tcp',
    'host' => '127.0.0.1',
    'port' => 6379,
]);
for ($i = 1; $i <= 10000; $i++) {
    $client->hset('hash2','key:'.$i,$i);
    $client->set('key:'.$i,$i);
}


HSCAN 查询

> HSCAN hash2 0 MATCH "key:99*" count 10000
1) "0"
2)   1) "key:9956"
     2) "9956"
     3) "key:9998"
     4) "9998"
     5) "key:9905"
     ....
     221) "key:9962"
     222) "9962"

SCAN 查询

> SCAN 0 match "key:99*" count 10000
1) "6655"
2)   1) "key:9956"
     2) "key:9998"
     3) "key:9905"
     ....
     109) "key:994"
     110) "key:9915"
> SCAN 6655 match "key:99*" count 10000
1) "0"
2) 1) "key:9962"

总结

HSCANSCAN 很大程度上是弥补 KEYS * 的不足;

在生产环境建议少使用 SCANKEYS * 等命令,一旦数据量大可能会导致宕机或者影响线上环境 Redis 插入和读写

如果观察到 Redis 的内存大起大落,这极有可能是因为大 key 导致的,需要定位出具体是那个 key,进一步定位出具体的业务来源,然后再改进相关业务代码设计。

普通查大key流程:

  • SCAN 扫码每一个key
  • TYPE 获取字段类型
  • SIZE 或者 LEN 得到他的大小

Redis 其实在redis-cli 提供了这个功能

redis-cli -h 127.0.0.1 -p 6379 --bigkeys

如果担心指令会大幅提升ops线上报警,可增加一个修满参数,但是查询时间会变长(休眠0.1s)

redis-cli -h 127.0.0.1 -p 6379 —bigkeys -i 0.1

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
2月前
|
存储 NoSQL Java
Redis如何处理Hash冲突?
在 Redis 中,哈希表是一种常见的数据结构,通常用于存储对象的属性,对于哈希表,最常遇到的是哈希冲突,那么,当 Redis遇到Hash冲突会如何处理?这篇文章,我们将详细介绍Redis如何处理哈希冲突,并探讨其性能和实现细节。
78 1
|
2月前
|
存储 NoSQL Redis
Redis 哈希(Hash)
10月更文挑战第16天
42 1
|
2月前
|
存储 分布式计算 NoSQL
大数据-40 Redis 类型集合 string list set sorted hash 指令列表 执行结果 附截图
大数据-40 Redis 类型集合 string list set sorted hash 指令列表 执行结果 附截图
29 3
|
3月前
|
存储 JSON NoSQL
redis基本数据结构(String,Hash,Set,List,SortedSet)【学习笔记】
这篇文章是关于Redis基本数据结构的学习笔记,包括了String、Hash、Set、List和SortedSet的介绍和常用命令。文章解释了每种数据结构的特点和使用场景,并通过命令示例演示了如何在Redis中操作这些数据结构。此外,还提供了一些练习示例,帮助读者更好地理解和应用这些数据结构。
redis基本数据结构(String,Hash,Set,List,SortedSet)【学习笔记】
|
3月前
|
存储 NoSQL 算法
5)深度解密 Redis 的哈希(Hash)
5)深度解密 Redis 的哈希(Hash)
32 0
|
4月前
|
存储 NoSQL 算法
Redis6入门到实战------ 三、常用五大数据类型(列表(List)、集合(Set)、哈希(Hash)、Zset(sorted set))
这是关于Redis 6入门到实战的文章,具体内容涉及Redis的五大数据类型:列表(List)、集合(Set)、哈希(Hash)、有序集合(Zset(sorted set))。文章详细介绍了这些数据类型的特点、常用命令以及它们背后的数据结构。如果您有任何关于Redis的具体问题或需要进一步的帮助,请随时告诉我。
|
5月前
|
存储 缓存 NoSQL
Redis问题之一致性Hash是如何解决哈希+取余方法中的稳定性问题的
Redis问题之一致性Hash是如何解决哈希+取余方法中的稳定性问题的
69 10
|
4月前
|
存储 缓存 NoSQL
redis数据结构-hash
redis数据结构-hash
28 0
|
5月前
|
消息中间件 JSON NoSQL
Redis深度解析:核心数据类型之hash、list、set
Redis深度解析:核心数据类型之hash、list、set
|
6月前
|
存储 JSON NoSQL
Redis第五弹-HASH结构相关指令和介绍,计数功能Hash-哈希(Redis本来就是键值对结构,哈希,就相当于键值对嵌套了一个键值对)的多种指令Hset key field value-
Redis第五弹-HASH结构相关指令和介绍,计数功能Hash-哈希(Redis本来就是键值对结构,哈希,就相当于键值对嵌套了一个键值对)的多种指令Hset key field value-