Redis核心数据结构实战

文章目录


概述

Redis有五种核心数据结构:

  1. String:标准的 key-value 结构:key -> value
  2. Hash:key -> field1:value1, field2:value2,类似双层 Map
  3. List:key -> 有序列表 [v1, v2, v3, ...]
  4. Set:key -> 无序、不重复元素集合 {v1, v2, v3}
  5. Zset:也称为sorted_set,key -> (member, score) 的集合,自动按 score 排序

一、String运用场景

String通常是项目中运用最多的场景,通常可用于单值缓存,对象缓存,计数器,生成ID序列等场景:

1.1、单值缓存

可运用于邮件验证码,短信验证码等临时信息的存储,这类数据的生命周期较短,没有必要存储在数据库中,在设置键时,通常是业务名称:用户手机号/邮箱这样的格式。

java 复制代码
phone:13211111111
email:13211111111@126.com

1.2、对象缓存

对象缓存和单值缓存的区别在于,对象缓存的value通常是转换为JSON格式的Java对象,在存储时进行序列化,查询时进行反序列化。

可用于缓存页面上列表的查询条件,键可以设置为业务名称:用户ID:页面上选择的查询条件

java 复制代码
fundlist:1:查询条件1_查询条件2_查询条件3

假设我有如下的数据:

id name age
1 zhagnsan 23
2 lisi 20
3 wanger 15

可以有两种存储的方式,方式一:

  • key:业务名称:用户ID
  • value:该用户ID对应的name和age,在java中是转换为json字符串的。
shell 复制代码
127.0.0.1:6379> SET user:1 "name:zhangsan age:23"
OK
127.0.0.1:6379> get user:1
"name:zhangsan age:23"

方式二,使用mset 命令:

  • key:业务名称:用户ID:某个属性名
  • value:该用户ID对应的属性名的属性值
shell 复制代码
127.0.0.1:6379> mset user:2:name zhangsan user:2:age 23
OK
127.0.0.1:6379> mset user:2:name lisi user:2:age 20
OK
127.0.0.1:6379> mget user:2:name
1) "lisi"

第二种方式的粒度更小,比第一种方式更加便于修改。第一种方式,存储的对象是一个整体,如果需要修改,则经过反序列化->修改->重新序列化的过程。而第二种方式细化到了对象的某个属性,针对于属性频繁修改的场景。

1.3、计数器

可以运用在文章阅读的计数,或者自增序列,该操作由Redis单线程保证原子性:

shell 复制代码
127.0.0.1:6379> INCR article:readcount:1
(integer) 1
127.0.0.1:6379> INCR article:readcount:1
(integer) 2
127.0.0.1:6379> INCR article:readcount:1
(integer) 3
127.0.0.1:6379> get article:readcount:1
"3"

1.4、批量生成序号

通过INCRBY命令获取批量序号,存入内存中进行分配使用:

shell 复制代码
127.0.0.1:6379> INCRBY orderId 1000
(integer) 1000
127.0.0.1:6379> get orderId
"1000"

二、Hash

Hash在项目中的运用场景,可以是对象缓存,以及临时购物车功能。Hash结构不建议存储单个key的value过大的数据,否则在集群环境下会造成数据倾斜

2.1、对象缓存

相比较于String,Hash适合结构扁平、字段不多、经常需要单独修改或读取某个字段的场景:

shell 复制代码
127.0.0.1:6379> hset user:3 name wanger age 18
(integer) 0
127.0.0.1:6379> hget user:3 name
"wanger"

2.2、临时购物车

电商网站,销售平台的临时购物车,也可以使用Redis的Hash结构进行存储:

  • key:业务名称:用户ID
    • field:商品ID
    • value:商品数量

加入购物车:

shell 复制代码
127.0.0.1:6379> hset cart:1 1 1
(integer) 1
127.0.0.1:6379> hset cart:1 2 5
(integer) 1

从购物车获取元素:

shell 复制代码
127.0.0.1:6379> hget cart:1 2
"5"

增加购物车数量

shell 复制代码
127.0.0.1:6379> HINCRBY cart:1 1 1
(integer) 2

购物车中一共有多少种类的商品

shell 复制代码
127.0.0.1:6379> HLEN cart:1
(integer) 2

删除某一样商品

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

获取购物车的所有商品

shell 复制代码
127.0.0.1:6379> HGETALL cart:1
1) "2"
2) "5"

三、List

List结构常用于实现分布式场景下的栈,队列,阻塞队列。在社交项目中,还可以实现消息的推送和接收

3.1、实现栈、队列、阻塞队列

实现先进后出的栈:

shell 复制代码
127.0.0.1:6379> lpush stack a
(integer) 1
127.0.0.1:6379> lpush stack b
(integer) 2
127.0.0.1:6379> lpush stack c
(integer) 3
127.0.0.1:6379> lpop stack
"c"

实现先进先出的队列:

shell 复制代码
127.0.0.1:6379> lpush queue 1
(integer) 1
127.0.0.1:6379> lpush queue 1
(integer) 2
127.0.0.1:6379> rpop queue
"1"

实现阻塞队列,需要设置超时时间

shell 复制代码
127.0.0.1:6379> lpush blocking_queue "1"
(integer) 1
127.0.0.1:6379> lpush blocking_queue "2"
(integer) 2
127.0.0.1:6379> brpop blocking_queue 5
1) "blocking_queue"
2) "1"
127.0.0.1:6379> brpop blocking_queue 5
1) "blocking_queue"
2) "2"
127.0.0.1:6379> brpop blocking_queue 5
(nil)
(5.01s)

3.2、消息推送

当微信公众号发送新文章时,需要推送给每一个订阅的用户:

  • key:业务名称:用户ID
  • value:消息ID
shell 复制代码
127.0.0.1:6379> LPUSH msg:1 1926
(integer) 1
127.0.0.1:6379> LPUSH msg:1 1848
(integer) 2
127.0.0.1:6379> LRANGE msg:1 0 4
1) "1848"
2) "1926"

客户端拿到消息ID后进行处理

四、Set

Set在项目中可以用于抽奖、点赞,收藏,以及共同关注的场景。

4.1、抽奖

用户在页面上点击一次抽奖,就向set集合中存放一个元素,利用set去重的特性,防止同一用户多次参与:

shell 复制代码
127.0.0.1:6379> sadd cj 1 2 3 4 5
(integer) 5
127.0.0.1:6379> sadd cj 1 2 3 4 5
(integer) 0

查看抽奖的用户

shell 复制代码
127.0.0.1:6379> SMEMBERS cj
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"

进行抽奖(SRANDMEMBER不会删除set中的元素,而SPOP会)

shell 复制代码
127.0.0.1:6379> SRANDMEMBER cj 2
1) "4"
2) "5"

4.2、点赞、收藏

点赞,收藏同样利用的是sadd、smembers等命令:

shell 复制代码
127.0.0.1:6379> sadd like:1848 1
(integer) 1

取消点赞:

shell 复制代码
127.0.0.1:6379> SREM like:1848 1
(integer) 1

查询用户是否点过赞

shell 复制代码
127.0.0.1:6379> sismember like:1848 1
(integer) 1

获取点赞的用户列表:

shell 复制代码
127.0.0.1:6379> SMEMBERS like:1848 
1) "1"

获取点赞的用户数量:

shell 复制代码
127.0.0.1:6379> SCARD like:1848
(integer) 1

4.3、集合操作

集合操作有交集,并集,差集,首先定义三个集合:

shell 复制代码
127.0.0.1:6379> sadd set1 a b c
(integer) 3
127.0.0.1:6379> sadd set2 b c
(integer) 2
127.0.0.1:6379> sadd set3 b c d e
(integer) 4

127.0.0.1:6379> SMEMBERS set1
1) "b"
2) "c"
3) "a"
127.0.0.1:6379> SMEMBERS set2
1) "b"
2) "c"
127.0.0.1:6379> SMEMBERS set3
1) "e"
2) "b"
3) "c"
4) "d"

交集是求集合1和集合2共有的部分:

shell 复制代码
127.0.0.1:6379> SINTER set1 set2
1) "b"
2) "c"

并集是求集合1和集合2所有的部分:

shell 复制代码
127.0.0.1:6379> sunion set1 set2
1) "b"
2) "a"
3) "c"

差集返回所有存在于第一个集合,但不存在于其他一个或多个集合中的成员:

shell 复制代码
127.0.0.1:6379> sdiff set1 set2 set3
1) "a"

五、ZSet

ZSet也称为sorted_set,继承了Set的功能之外,增加了排序的功能,可使用于项目中的排行榜功能。

点击新闻:

shell 复制代码
127.0.0.1:6379> ZINCRBY hotnews:20250622 1 hotnews1
"1"
127.0.0.1:6379> ZINCRBY hotnews:20250622 1 hotnews1
"2"
127.0.0.1:6379> ZINCRBY hotnews:20250622 1 hotnews1
"3"
127.0.0.1:6379> ZINCRBY hotnews:20250622 1 hotnews1
"4"
127.0.0.1:6379> ZINCRBY hotnews:20250622 1 hotnews2
"1"
127.0.0.1:6379> ZINCRBY hotnews:20250622 1 hotnews2
"2"
127.0.0.1:6379> ZINCRBY hotnews:20250622 1 hotnews3
"1"

展示当日排行

shell 复制代码
127.0.0.1:6379> ZREVRANGE hotnews:20250622 0 10 withscores
1) "hotnews1"
2) "4"
3) "hotnews2"
4) "2"
5) "hotnews3"
6) "1"

展示多日榜单

shell 复制代码
127.0.0.1:6379> ZINCRBY hotnews:20250621 1 hotnews3
"1"
127.0.0.1:6379> ZINCRBY hotnews:20250620 1 hotnews3
"1"
127.0.0.1:6379> ZREVRANGE hotnews:20250620-20250622 0 10 withscores
1) "hotnews1"
2) "4"
3) "hotnews3"
4) "3"
5) "hotnews2"
6) "2"
相关推荐
肖笙XiaoSheng10 分钟前
使用Gemini2.5 pro 优化我的定时任务(二)
java·后端·代码规范
小小霸王龙!12 分钟前
互联网大厂Java面试实录:Spring Boot与微服务在电商场景中的应用
java·spring boot·redis·微服务·电商
深栈解码14 分钟前
JUC并发编程 CAS运行机制详解
java·后端
草履虫建模15 分钟前
Postman - API 调试与开发工具 - 标准使用流程
java·测试工具·spring·json·测试用例·postman·集成学习
深栈解码15 分钟前
JUC并发编程 ThreadLocal解析
java·后端
衍生星球22 分钟前
Maven 3.9.6的下载和配置
java·maven·springboot
缘来是庄29 分钟前
设计模式之代理模式
java·设计模式·代理模式
roman_日积跬步-终至千里33 分钟前
【学习线路】机器学习线路概述与内容关键点说明
人工智能·学习·机器学习
都叫我大帅哥36 分钟前
向量数据库Milvus:非结构化数据的救星,AI开发者的瑞士军刀
java·python
都叫我大帅哥39 分钟前
Redis BitMap 深度解剖:比特世界的精密引擎
redis