Redis string和hash数据类型

一、redis 数据存储格式

redis自身是一个Map,其中所有的数据都是采用key:value的形式存储,数据类型指的是存储的value的类型,key部分永远都是字符串

在这里插入图片描述

二、string

存储的数据:单个数据,最简单数据存储类型,也是最常用的数据存储类型
存储数据的格式:一个存储空间保存一个数据
存储内容:通常使用字符串,如果字符串以整数的形式展示,可以作为数字操作使用

在这里插入图片描述

1. string基本操作

添加/修改多个数据

mset key1 valueq key2 value2 …

获取多个数据

mget key1 key2 …

在这里插入图片描述

获取数据字符个数(value的长度)

strlen key

追加信息到原始信息后部(如果原始信息存在就追加,否则新建)

append key value

在这里插入图片描述

单数据操作和多数据操作有什么区别?

在这里插入图片描述

操作同样数据量的情况下,单指令发送和接收次数多。我们使用的时候需要权衡,如果我们一次性发送的数据太少,就会导致频繁的收发,效率极低。如果我们一次性发过多的数据,由于redis服务器是单线程模型,请求无法得到即使的处理。最好的情况是,大量数据切分成多分小数据,让redis服务器能及时处理,也能保证收发次数不会过多

2. string扩展操作

业务场景一

大型企业级应用中,分表操作是基本操作,使用多张表存储同类型数据,但是对应的主键id必须保证统一性,不能重复。Oracle数据库具有sequence设定,可以解决该问题,但是MySQL数据库并不具有类似的机制,那么如何解决?

redis解决方案:

设置数值数据增加指定范围的值

incr key
incrby key 数值(正/负)
incrbyfloat key 数值(正/负)

设置数值数据减少指定范围的值

decr key
decrby key 数值(正/负)

在这里插入图片描述

在这里插入图片描述

String作为数值操作

  • string在redis内部存储默认就是一个字符串,当遇到增减类操作incr,decr时会转成数值型进行计算
  • redis所有的操作都是原子性的,采用单线程处理所有业务,命令是一个一个执行的,因此无需考虑并发带来的数据影响。
  • 注意:按数值进行操作的数据,如果原始数据不能转成数值,或超过了redis数值上限范围,将会报错。9223372036854775807 (java中long型数据最大值,Long.MAX_VALUE)

Tips1:

  • redis的单线程、原子性等用于控制数据库表主键id,为数据库表主键提供生成策略,保障数据库表的主键唯一性
  • 此方案适用于所有数据库,且支持数据库集群

业务场景二

  1. “最强女生”启动海选投票,只能通过微信投票,每个微信号每 4 小时只能投1票。
  2. 电商商家开启热门商品推荐,热门商品不能一直处于热门期,每种商品热门期维持3天,3天后自动取消热门
  3. 新闻网站会出现热点新闻,热点新闻最大的特征是时效性,如何自动控制热点新闻的时效性。

以上三点场景说的都是信息在一段时间之内有效 ,比如我们要实现4小时有效的数据,我们可以给数据设置有效时间为4小时,时间过了就删除该数据,用户可以继续投票

setex key 秒  数值                  # 秒
psetex key 毫秒  数值            # 毫秒

在这里插入图片描述

在这里插入图片描述

Tips 2:

  • redis 控制数据的生命周期,通过数据是否失效控制业务行为,适用于所有具有时效性限定控制的操作

业务场景三

主页高频访问信息显示控制,例如新浪微博大V主页显示粉丝数与微博数量需要实时刷新

在这里插入图片描述

redis中可以以两种方式存储这些数据

在这里插入图片描述
第一种方式修改value较简单,但是需要存储多条数据,查看不方便;第二种方式查看方便,但是修改较麻烦

Tips 3:

  • redis应用于各种结构型和非结构型高热度数据访问加速

3. 数据库中热点数据key命名规范

在这里插入图片描述

4. string类型注意事项

数据操作不成功的反馈与数据正常操作之间的差异

  • 表示运行结果是否成功:(integer)0–>false 失败、(integer)1–>true 成功
  • 表示运行结果值:(integer)3、(integer)1
  • 数据未获取到:(nil)等同于null

数据最大存储量:512MB
数值计算最大范围:java中的long的最大值,9223372036854775807

三、hash

在这里插入图片描述
我们用这种json的方式存储数据,查看数据很方便,修改数据较麻烦

在这里插入图片描述
第二种方式修改起来很方便,查看又不方便了

在这里插入图片描述

我们使用第三种hash的方式存储,这就能做到读取和修改都方便了,现在一个key对应一个hash类型的数据,我们把value理解为一个字典即可

1. hash类型介绍

  • 新的存储需求:对一系列存储的数据进行编组,方便管理,典型应用存储对象信息
  • 需要的内存结构:一个存储空间保存多少个键值对数据
  • hash类型:底层使用哈希表结构实现数据存储

在这里插入图片描述

2. hash类型基本操作

添加/修改数据

hset key field value

在这里插入图片描述

获取数据

hget key field
hgetall key

在这里插入图片描述

删除数据

hdel key field1 [field2]

在这里插入图片描述

添加/修改多个数据

hmset key field1 value1 field2 value2

获取多个数据

hmget key field1 field2 …

在这里插入图片描述

获取哈希表中field的数量

hlen key

在这里插入图片描述

获取哈希表中是否存在指定的字段

hexists key field

在这里插入图片描述

3. hash类型扩展操作

获取哈希表中所有的字段名和字段值

hkeys key     # 获取key对应的hash数据类型中所有field
hvals key     # 获取key对应的hash数据类型中所有value

在这里插入图片描述

设置指定字段的数值数据增加指定范围的值

hincrby key field increment
hincrbyfloat key field increment

在这里插入图片描述

4. hash类型数据操作的注意事项

  • hash类型下的value只能存储字符串,不允许存储其他类型数据,不存在嵌套现象。如果数据未获取到,对应的值为(nil)

  • 每个hash类型可以存储 2 32 − 1 2^{32}-1 2321个键值对

  • hash类型十分贴近对象的数据存储形式,并且可以灵活添加删除对象属性。但hash设计初衷不是为了存储大量对象而设计的,切记不可滥用,更不可以将hash作为对象列表使用

  • hgetall操作可以获取key对应哈希类型所有的field以及value,如果内部field过多,遍历整体数据效率就会很低,有可能成为数据访问瓶颈,所以一般建议用哪个取哪个,不建议hgetall全部获取

5. hash类型实际应用场景

购物车场景一

在这里插入图片描述

电商购物车中,将用户的id作为key;商品id作为field;数量作为value;hget可以获取value;hincrby增加value;hset设置value;删除商品就是删除一个field,可以使用hdel;全选所有商品,即获取所有的field,可以使用hgetall;商品数量即field的个数,可以使用hlen

127.0.0.1:6379> hmset user1 g01 100 g02 200          # user1在购物车添加100个g01商品,200个g02商品
OK
127.0.0.1:6379> hmset user2 g02 1 g04 7 g05 100      # user2在购物车添加1个g02商品,7个g04商品,100个g05商品
OK
127.0.0.1:6379> hset user1 g03 5                     # user1在购物车中添加5个g03
(integer) 1
127.0.0.1:6379> hgetall user1                        # 查看user1的购物车
1) "g01"
2) "100"
3) "g02"
4) "200"
5) "g03"
6) "5"
127.0.0.1:6379> hdel user1 g01                      # user1删除购物车的g01商品
(integer) 1
127.0.0.1:6379> hgetall user1                       # 查看user1的购物车
1) "g02"
2) "200"
3) "g03"
4) "5"
127.0.0.1:6379> hincrby user1 g03 1                 # user1在购物车增加1个g03商品
(integer) 6
127.0.0.1:6379> hgetall user1                       # 查看user1的购物车
1) "g02"
2) "200"
3) "g03"
4) "6"
127.0.0.1:6379> 

当前设计是否加速了购物车的呈现?

当前仅仅是将数据存储到redis中,还需要通过磁盘IO查询数据库,用商品id查询出商品的描述信息,然后将得到的数据传给前端显示给用户,并没有起到加速的作用

我们用如下方式解决,不经过磁盘IO查询数据库,所有的数据都存放在redis

在这里插入图片描述

在这里插入图片描述

这个方法也是有缺点的,假如还有很多用户也购买了g01商品,那redis就会很多份g01商品的描述信息,这就在内存上存在重复存储

在这里插入图片描述

于是我们将商品描述信息独立存储成一个hash类型,就不会重复存储了,用户存储商品id,就能通过商品id在redis中查找商品信息。商品被购买了,就要到这个hash存储中添加信息

那每次买东西都添加商品信息,这不也会重复吗?我们使用hsetnx,已经添加过的商品(field)就不会再添加,相当于hexists + hset

hsetnx :key对应的hash类型中,有field就不修改value,没有field就设置为value
hset:key对应的hash类型中,无论有没有field,都设置为value

hsetnx key field value 

在这里插入图片描述
销售场景二

双11活动日,销售手机充值卡的商家对移动、联通、电信的30元、50元、100元商品推出抢购活动,每种商品抢购上限1000张

在这里插入图片描述
以商家id作为key、将参与抢购的商品id作为field、将参与抢购的商品数量作为对应的value、抢购时使用降值的方式控制产品数量

在这里插入图片描述
redis只做数据的修改和保存,尽量不要把业务相关的操作放在redis上,比如判断是否存在等

string存储对象(json)与hash存储对象的区别:string存储对象讲究整体性,要么一次性更新,要么一次性获取,以读为主;hash存储可以把属性用field隔离开,比较灵活,便于修改

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bugcoder-9905

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值