您当前的位置:首页 > 文章 > Redis 入门到精通(一)数据类型(2)

Redis 入门到精通(一)数据类型(2)

作者:段子手-168 时间:2024-07-12 阅读数:212 人阅读

一、redis 数据类型–hash 类型介绍与基本操作

1、hash 类型

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

5-hash存储空间.png

2、hash 存储结构优化

  • 如果 field 数量较少,存储结构优化为类数组结构。
  • 如果 field 数量较多,存储结构使用HashMap结构。

3、hash 类型数据的基本操作

# 1)添加/修改数据
hset key field value
# 获取数据
hget key field
hgetall key
# 删除数据
hdel key fieldl [field2]
# 范例:
127.0.0.1:6379> hset zsf name zhangsanfeng
(integer) 1
127.0.0.1:6379> hset zsf age 101
(integer) 1
127.0.0.1:6379> hset zsf weight 80
(integer) 1
127.0.0.1:6379> hget zsf age
"101"
127.0.0.1:6379> hgetall zsf
1) "name"
2) "zhangsanfeng"
3) "age"
4) "101"
5) "weight"
6) "80"
127.0.0.1:6379>
# 2)添加/修改多个数据
hmset key fieldl valuel field2 value2

# 获取多个数据
hmget key fieldl field2...
# 获取哈希表中字段的数量
hlen key
# 获取哈希表中是否存在指定的字段
hexists key field
# 范例:
127.0.0.1:6379> hmget zsf name age
1) "zhangsanfeng"
2) "101"
127.0.0.1:6379> hmset zsf name lixiaolong age 38
OK
127.0.0.1:6379> hgetall zsf
1) "name"
2) "lixiaolong"
3) "age"
4) "38"
5) "weight"
6) "80"
127.0.0.1:6379>

127.0.0.1:6379> hlen zsf
(integer) 3
127.0.0.1:6379> hexists zsf age
(integer) 1
127.0.0.1:6379> hexists zsf hight
(integer) 0
127.0.0.1:6379>

二、redis 数据类型–hash 扩展操作与使用注意事项

1、hash 类型数据扩展操作

# 获取哈希表中所有的字段名或字段值
hkeys key 
hvals key 

# 设置指定字段的数值数据增加指定范围的值
hincrby key field increment 
hincrbyfloat key field increment 

# 范例: 
127.0.0.1:6379> hkeys zsf
1) "name"
2) "age"
3) "weight"
127.0.0.1:6379> hvals zsf
1) "lixiaolong"
2) "38"
3) "80"
127.0.0.1:6379> hset zsf weight 38
(integer) 0
127.0.0.1:6379> hvals zsf
1) "lixiaolong"
2) "38"
3) "38"
127.0.0.1:6379> hincrby zsf age 2
(integer) 40
127.0.0.1:6379>

2、hash 类型数据操作的注意事项

  • hash 类型下的 value 只能存储字符串,不允许存储其他数据类型,不存在嵌套现象。如果数据未获取到对应的值为(nil)。
  • 每个 hash 可以存储 232 - 1 个键值对。
  • hash 类型十分贴近对象的数据存储形式,并且可以灵活添加删除对象属性。但hash设计初衷不是为了存储大量对象而设计的,切记不可滥用,更不可以将hash作为对象列表使用。
  • hgetal 操作可以获取全部属性,如果内部 field 过多,遍历整体数据效率就很会低,有可能成为数据访问瓶颈。

三、redis 数据类型–hash 实现购物车

1、hash 类型应用场景:业务场景–电商网站购物车设计与实现

1)业务分析

  • 仅分析购物车的 redis 存储模型添加、浏览、更改数量、删除、清空。
  • 购物车于数据库间持久化同步(不讨论)。
  • 购物车于订单间关系(不讨论 )。
    提交购物车:读取数据生成订单。
    商家临时价格调整:隶属于订单级别。
  • 未登录用户购物车信息存储(不讨论)。
    cookie 存储。

6-redis电商网站购物车设计与实现.png

2)解决方案

  • 以客户 id 作为 key,每位客户创建一个 hash 存储结构存储对应的购物车信息。
  • 将商品编号作为 field,购买数量作为 value 进行存储。
  • 添加商品:追加全新的 field 与 value。
  • 浏览:遍历 hash。
  • 更改数量:自增/自减,设置 value 值。
  • 删除商品:删除 field。
  • 清空:删除 key。
  • 此处仅讨论购物车中的模型设计。
  • 购物车与数据库间持久化同步、购物车与订单间关系、未登录用户购物车信息存储不进行讨论。

2、redis 实际模拟操作:

# 如:用户01,购买商品g01, 100个,购买商品g02,200个
127.0.0.1:6379> hmset user01 g01 100 g02 200
OK

# 如:用户02,购买商品g02, 1个,购买商品g04,7个,购买商品g05,100个,
127.0.0.1:6379> hmset user02 g02 1 g04 7 g05 100
OK

# 如:用户01,再次购买商品g03, 5个,
127.0.0.1:6379> hset user01 g03 5
(integer) 1

# 如:查询 用户01 购买的商品和数量
127.0.0.1:6379> hgetall user01
1) "g01"
2) "100"
3) "g02"
4) "200"
5) "g03"
6) "5"
127.0.0.1:6379>

# 如:用户01 不需要商品g01(删除商品)
127.0.0.1:6379> hdel user01 g01
(integer) 1
127.0.0.1:6379> hgetall user01
1) "g02"
2) "200"
3) "g03"
4) "5"
127.0.0.1:6379>

# 如:用户01 添加商品g03(购物)1个
127.0.0.1:6379> hincrby user01 g03 1
(integer) 6
127.0.0.1:6379> hgetall user01
1) "g02"
2) "200"
3) "g03"
4) "6"
127.0.0.1:6379>

3、hash 类型应用场景:当前设计是否加速了购物车的呈现?

当前仅仅是将数据存储到了 redis 中,并没有起到加速的作用,商品信息还需要二次查询数据库。

  • 每条购物车中的商品记录保存成两条 field
  • field1 专用于保存购买数量
    命名格式:商品id:nums
    保存数据:数值
  • field2 专用于保存购物车中显示的信息,包含文字描述,图片地址,所属商家信息等
    命名格式:商品id:info
    保存数据:json

4、redis 实际模拟操作:

# 用户03 购物商品g01,关联数量nums, 100个,商品g01信息info, 为【...】暂时省略。
127.0.0.1:6379> hmset user03 g01:nums 100 g01:info [...]
OK
127.0.0.1:6379> hgetall user03
1) "g01:nums"
2) "100"
3) "g01:info"
4) "[...]"
127.0.0.1:6379>

# 用户04 也购物商品g01,关联数量nums, 5个,商品g01信息info, 为【...】暂时省略。大量重复信息
127.0.0.1:6379> hmset user04 g01:nums 5 g01:info [...]
OK
127.0.0.1:6379> hgetall user04
1) "g01:nums"
2) "5"
3) "g01:info"
4) "[...]"
127.0.0.1:6379>
# 独立 hash,有值,不操作,无值,再添加,就避免大量重复信息与重复操作,效率提高。
# 命令:hsetnx key field value

# 如:正常修改 用户03,商品g01的数量nums 为 200,成功
127.0.0.1:6379> hset user03 g01:nums 200
(integer) 0
127.0.0.1:6379> hgetall user03
1) "g01:nums"
2) "200"
3) "g01:info"
4) "[...]"

# 如:通过 hsetnx 修改 用户03,商品g01的数量nums 为 400,发现商品g01有值,不操作,修改失败。
127.0.0.1:6379> hsetnx user03 g01:nums 400
(integer) 0

# 如:通过 hsetnx 修改 用户03,添加商品g05的数量nums 为 1,发现没有商品g05,添加成功
127.0.0.1:6379> hsetnx user03 g05:nums 1
(integer) 1
127.0.0.1:6379> hgetall user03
1) "g01:nums"
2) "200"
3) "g01:info"
4) "[...]"
5) "g05:nums"
6) "1"
127.0.0.1:6379>

5、redis 应用场景:

1)redis 用于控制数据库表主键 id,为数据库表主键提供生成策略,保障数据库表的主键唯一性此方案适用于所有数据库,且支持数据库集群。

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

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

4)redis 应用于购物车数据存储设计。

四、redis 数据类型–hash 实现抢购

1、hash 类型应用场景: 业务场景

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

7-手机充值卡.png

2、hash 类型应用场景:解决方案

  • 以商家 id 作为 key。
  • 将参与抢购的商品 id 作为 field。
  • 将参与抢购的商品数量作为对应的 value。
  • 抢购时使用降值的方式控制产品数量。
  • 实际业务中还有超卖等实际问题,这里不做讨论。

3、redis 实际模拟操作:

# 如:商家p01, 有 30元、50元、100元手机充值卡各 1000 张。
127.0.0.1:6379> hmset p01 c30 1000 c50 1000 c100 1000
OK

# 商家p01,销售出去50元一张
127.0.0.1:6379> hincrby p01 c50 -1
(integer) 999

# 商家p01,销售出去100元20张
127.0.0.1:6379> hincrby p01 c100 -20
(integer) 980
127.0.0.1:6379> hgetall p01
1) "c30"
2) "1000"
3) "c50"
4) "999"
5) "c100"
6) "980"
127.0.0.1:6379>

4、redis 应用场景:

1)redis 用于控制数据库表主键 id,为数据库表主键提供生成策略,保障数据库表的主键唯一性此方案适用于所有数据库,且支持数据库集群。

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

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

4)redis 应用于购物车数据存储设计。

5)redis 应用于抢购,限购类、限量发放优惠卷、激活码等业务的数据存储设计。

五、redis 数据类型–list 类型介绍与基本操作

1、list 类型

  • 数据存储需求: 存储多个数据,并对数据进入存储空间的顺序进行区分。
  • 需要的存储结构: 一个存储空间保存多个数据,且通过数据可以体现进入顺序。
  • list 类型: 保存多个数据,底层使用双向链表存储结构实现。

8-list类型.png

2、list 类型数据基本操作–添加/修改数据

# 添加/修改数据
lpush key valuel [value2]
rpush key valuel [value2]

3、list 类型数据基本操作–获取数据

# 获取数据
lrange key start stop
lindex keyindex
1len key

4、list 类型数据基本操作–获取并移除数据

# 获取并移除数据
lpop key
rpop key

5、redis 实际模拟操作:

# 从左边插入数据
127.0.0.1:6379> lpush list1 huawei
(integer) 1
127.0.0.1:6379> lpush list1 apple
(integer) 2
127.0.0.1:6379> lpush list1 microsoft
(integer) 3

# 从左边获取数据
127.0.0.1:6379> lrange list1 0 2
1) "microsoft"
2) "apple"
3) "huawei"

# 从右边插入数据
127.0.0.1:6379> rpush list2 a b c
(integer) 3

# 从左边获取数据
127.0.0.1:6379> lrange list2 0 2
1) "a"
2) "b"
3) "c"

# 从左边获取数据(未知总数)
127.0.0.1:6379> lrange list1 0 -1
1) "microsoft"
2) "apple"
3) "huawei"
127.0.0.1:6379> lrange list1 0 -2
1) "microsoft"
2) "apple"
127.0.0.1:6379> lrange list1 0 -3
1) "microsoft"
127.0.0.1:6379> lrange list1 0 -4
(empty list or set)
127.0.0.1:6379> lrange list1 -1 0
(empty list or set)
127.0.0.1:6379>

# 获取指定元素
127.0.0.1:6379> lindex list1 0
"microsoft"
127.0.0.1:6379> lindex list2 1
"b"
127.0.0.1:6379> lindex list1 1
"apple"
127.0.0.1:6379> lindex list1 2
"huawei"
127.0.0.1:6379> lindex list2 0
"a"
127.0.0.1:6379> lindex list2 2
"c"

# 获取数据长度
127.0.0.1:6379> llen list1
(integer) 3
127.0.0.1:6379> llen list2
(integer) 3
127.0.0.1:6379>

# 获取并移除数据 
127.0.0.1:6379> lpush list3 a b c
(integer) 3
127.0.0.1:6379> lpop list3
"c"
127.0.0.1:6379> llen list3
(integer) 2
127.0.0.1:6379> lpop list3
"b"
127.0.0.1:6379> lpop list3
"a"
127.0.0.1:6379> lpop list3
(nil)
127.0.0.1:6379> llen list3
(integer) 0
127.0.0.1:6379>

六、redis 数据类型–list 阻塞数据获取

1、list 类型数据扩展操作:规定时间内获取并移除数据

blpop keyl [key2]timeout
brpop keyl [key2] timeout
brpoplpush source destination timeout

2、redis 实际模拟操作:

# 打开一个客户端
127.0.0.1:6379> lpush list0 a b
(integer) 2
127.0.0.1:6379> lpop list0
"b"
127.0.0.1:6379> lpop list0
"a"
127.0.0.1:6379> lpop list0
(nil)
127.0.0.1:6379> blpop list0 30
1) "list0"
2) "c"
127.0.0.1:6379> blpop list0 5
(nil)
(5.09s)
127.0.0.1:6379> blpop list0 10
1) "list0"
2) "d"
(2.42s)
127.0.0.1:6379>

# 另外打开一个客户端
127.0.0.1:6379> lpush list0 c
(integer) 1
127.0.0.1:6379> lpush list0 d
(integer) 1
127.0.0.1:6379>

9-list类型扩展-1.png

七、redis 数据类型–list 扩展操作删除数据

1、list 类型数据扩展操作:业务场景

微信朋友圈点赞,要求按照点赞顺序显示点赞好友信息如果取消点赞,移除对应好友信息。

10-list类型扩展-2.png

2、解决方案:使用 redis 移除指定数据

# 移除指定数据
lrem key count value

3、redis 实际模拟操作:

# 从右边插入 5 个数据
127.0.0.1:6379> rpush daqiao a b c d e
(integer) 5

# 从左边获取全部数据
127.0.0.1:6379> lrange daqiao 0 -1
1) "a"
2) "b"
3) "c"
4) "d"
5) "e"

# 删除指定数据(1 个 d)
127.0.0.1:6379> lrem daqiao 1 d
(integer) 1
127.0.0.1:6379> lrange daqiao 0 -1
1) "a"
2) "b"
3) "c"
4) "e"
127.0.0.1:6379>

# 从右边插入 多条有重复的数据
127.0.0.1:6379> rpush daqiao a b a b a b c d a c e
(integer) 15
127.0.0.1:6379> lrange daqiao 0 -1
 1) "a"
 2) "b"
 3) "c"
 4) "e"
 5) "a"
 6) "b"
 7) "a"
 8) "b"
 9) "a"
10) "b"
11) "c"
12) "d"
13) "a"
14) "c"
15) "e"

# 从左边开始,删除指定数据(4 个 a)
127.0.0.1:6379> lrem daqiao 4 a
(integer) 4
127.0.0.1:6379> lrange daqiao 0 -1
 1) "b"
 2) "c"
 3) "e"
 4) "b"
 5) "b"
 6) "b"
 7) "c"
 8) "d"
 9) "a"
10) "c"
11) "e"
127.0.0.1:6379>

4、redis 应用场景:

1)redis 用于控制数据库表主键 id,为数据库表主键提供生成策略,保障数据库表的主键唯一性此方案适用于所有数据库,且支持数据库集群。

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

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

4)redis 应用于购物车数据存储设计。

5)redis 应用于抢购,限购类、限量发放优惠卷、激活码等业务的数据存储设计。

6)redis 应用于具有操作先后顺序的数据控制。

八、redis 数据类型–list 实现日志消息队列

1、Iist 类型数据操作注意事项

  • list 中保存的数据都是 string 类型的,数据总容量是有限的,最多 232-1个元素 (4294967295)。
  • list 具有索引的概念,但是操作数据时通常以队列的形式进行入队出队操作,或以栈的形式进行入栈出栈操作。
  • 获取全部数据操作结束索引设置为 -1。
  • list 可以对数据进行分页操作,通常第一页的信息来自于 list,第2页及更多的信息通过数据库的形式加载。

2、list 类型应用场景:

1)业务场景1

twitter、新浪微博、腾讯微博中个人用户的关注列表需要按照用户的关注顺序进行展示,粉丝列表需要将最近关注的粉丝列在前面。

11-业务场景1.png

2)业务场景2

  • twitter、新浪微博、腾讯微博中个人用户的关注列表需要按照用户的关注顺序进行展示,粉丝列表近关注的粉丝列在前面。
  • 新闻、资讯类网站如何将最新的新闻或资讯按照发生的时间顺序展示?
  • 企业运营过程中,系统将产生出大量的运营数据,如何保障多台服务器操作日志的统一顺序输出?

11-业务场景2.png

3)list 类型应用场景–解决方案

  • 依赖 list 的数据具有顺序的特征对信息进行管理。
  • 使用队列模型解决多路信息汇总合并的问题。
  • 使用栈模型解决最新消息的问题。

3、redis 实际模拟操作–list 实现日志消息队列:

# 终端一从右边插入日志数据
127.0.0.1:6379>
127.0.0.1:6379> rpush logs a1..
(integer) 1
127.0.0.1:6379> rpush logs a2...
(integer) 2

# 查询数据
127.0.0.1:6379> lrange logs 0 -1
1) "a1.."
2) "a2..."
3) "b1.."
4) "b2..."
5) "c1.."
6) "c2..."
127.0.0.1:6379>

# 终端二从右边插入日志数据
127.0.0.1:6379> rpush logs b1..
(integer) 3
127.0.0.1:6379> rpush logs b2...
(integer) 4
127.0.0.1:6379>

# 终端三从右边插入日志数据
127.0.0.1:6379>
127.0.0.1:6379> rpush logs c1..
(integer) 5
127.0.0.1:6379> rpush logs c2...
(integer) 6
127.0.0.1:6379>

12-list类型实现日志消息队列.png

4、redis 应用场景:

1)redis 用于控制数据库表主键 id,为数据库表主键提供生成策略,保障数据库表的主键唯一性此方案适用于所有数据库,且支持数据库集群。

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

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

4)redis 应用于购物车数据存储设计。

5)redis 应用于抢购,限购类、限量发放优惠卷、激活码等业务的数据存储设计。

6)redis 应用于具有操作先后顺序的数据控制。

7)redis 应用于最新消息展示。

来源:https://dzs168.blog.csdn.net/article/details/140276467

本站大部分文章、数据、图片均来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了您的权益请来信告知我们删除。邮箱:1451803763@qq.com