当前位置: 首页 > news >正文

【Redis】Redis的5种核心数据结构和实战场景对应(在项目中的用法)

【Redis】Redis的5种核心数据结构和实战场景对应(在项目中的用法)

    • 一、String
      • 1. 缓存对象
      • 2. 分布式锁
      • 3. 共享Session
      • 4. 计数器:记录访问量/播放量
      • 5. 计数器限流:简单的流量控制
    • 二、Hash
      • 1. 存储对象
      • 2. 购物车
      • 3. 简单的动态配置管理
      • 4. 多维度统计:按分类计数
    • 三、List
      • 1. 简单消息队列
      • 2. 实时消息流:朋友圈/动态展示
      • 3. 栈结构:实现“最近访问”功能
    • 四、Set
      • 1. 抽奖系统
      • 2. 白名单/黑名单
      • 3. 点赞功能
      • 4. 集合运算:共同好友/共同兴趣
    • 五、ZSet
      • 1. 排行榜
      • 2. 滑动窗口限流
      • 3. 浏览记录
      • 4. 在线用户列表
    • 补充:Stream

一、String

String 就是单个的 KV 结构,用法灵活,是 Redis 最基础也最常用的数据结构之一。

1. 缓存对象

把高频访问的对象(比如用户信息、商品详情)序列化成JSON字符串,以“业务标识+ID”为key存入Redis,比如user:info:1001,value存用户信息的JSON串。
优势:减轻数据库压力,查询速度从毫秒级(数据库)降到微秒级(Redis);还能通过设置过期时间,自动淘汰冷门数据。

2. 分布式锁

利用String的SET NX EX命令(不存在则设置,同时加过期时间)实现分布式锁:

  • 线程抢锁时执行SET lock:order true NX EX 10,成功则拿到锁,失败则等待重试;
  • 执行完业务后用DEL lock:order释放锁,也能靠过期时间避免“死锁”(比如线程崩溃没释放,过期后自动解锁)。
    注意:实际使用时需配合“锁续期”(比如Redisson的看门狗机制),避免业务没执行完锁就过期。

3. 共享Session

分布式系统中,用户登录时生成一个 Token,以 Token 为 key、用户信息为 value,设置过期时间存到 Redis;

用户一段时间没访问系统,Token 就过期失效,需要重新登录;

只要用户访问,就通过拦截器给 Token 续期。

优势:替代传统的“服务器存Session”,实现多服务间的登录状态共享。

4. 计数器:记录访问量/播放量

利用String的原子自增命令INCR,实现无并发问题的计数器:

以网页路径或视频 ID 为 key,次数为 value,访问一次就自增一次,实现记录器效果。

  • 统计网页访问量:以page:view:/home为key,每次访问执行INCR page:view:/home
  • 统计视频播放量:以video:play:10086为key,每次播放执行INCR video:play:10086

特点:原子操作,不用担心多线程并发导致的计数不准。

5. 计数器限流:简单的流量控制

针对IP或接口做限流,比如“每个IP每分钟最多访问120次”:

  • 以 IP 或接口路径为 key,访问次数为 value,访问一次就自增一次,并设置过期时间60秒;
  • 若自增后的值超过120,则拒绝请求。

注意:这种方式有“临界问题”——比如第60秒来了120次请求,第61秒又来120次,两分钟内实际访问了240次,需结合滑动窗口限流(下文ZSet会讲)优化。

二、Hash

Hash 结构可以理解为能存储多组 KV 的 String,适合对对象字段做精细操作。

1. 存储对象

比如存用户信息,不用把整个用户JSON串存在String里,而是用Hash拆分字段:

  • key为user:1001,field为name(值:张三)、age(值:25)、phone(值:138xxxx);
  • 若要修改用户年龄,直接执行HSET user:1001 age 26,不用重新序列化整个对象。

优势:减少数据传输量,修改单个字段更高效。

2. 购物车

以用户ID为Hash的key,商品ID为field,商品数据为value:

  • 用户添加商品:HSET cart:user:1001 goods:2001 "数量:2,规格:红色"
  • 用户修改数量:HSET cart:user:1001 goods:2001 "数量:3,规格:红色"
  • 用户删除商品:HDEL cart:user:1001 goods:2001
  • 查看购物车:HGETALL cart:user:1001

特点:天然适配购物车的“用户-商品”对应关系,操作灵活。

3. 简单的动态配置管理

比如做功能开关或动态参数管理,以 “configure:xxx” 为 key,功能名称为 field,true/false 为 value,相当于把 Redis 当成简单的配置中心。

但 Redis 基于内存,可靠性不足,且配置发布变更没有权限管控,有一定风险,最好用 Nacos或 Apollo 这类专业配置中心;如果系统不想引入重依赖,只用 Redis 做简单配置也完全可行。

4. 多维度统计:按分类计数

比如记录不同地区的视频访问量,以视频 ID 为 key,地区为 field,访问次数为 value,访问一次就自增一次,实现不同地区视频访问量的记录。
优势:不用创建多个String键,一个Hash就能聚合同一维度的多个统计数据。

三、List

List 本质是双端队列,有序且可重复,既能当先进先出的队列,也能当后进先出的栈。

1. 简单消息队列

用List的LPUSH(从尾部加消息)和BRPOP(阻塞从头部取消息)实现消息队列:

  • 生产者发消息:LPUSH queue:order "订单ID:1001,状态:待支付"

  • 消费者取消息:BRPOP queue:order 0(0表示永久阻塞,直到有消息)。

消息幂等性:要保证消息不重复处理(幂等性),需给消息分配唯一 ID,消费者保存已处理的消息 ID,避免重复消费。

不过 List 做消息队列有局限:无法实现消息持久化、没有死信队列,也不能让多个消费者共享一条消息。如果系统较小,不想引入重量级 MQ,用 Redis List 做消息队列能满足基本需求;若 Redis 版本较高,可用 Stream——Stream 是 Redis 高版本专门的消息队列工具,功能更丰富,更接近完整的消息队列,和正式 MQ 相比还有缺陷,但整体已好很多,不想引入重 MQ 的话,用 Stream 或 List 都可以。

2. 实时消息流:朋友圈/动态展示

以用户ID作为List的key,消息 ID 为 value 存入 List:

  • 用户发朋友圈:LPUSH feed:user:1001 "动态ID:5001,内容:今天去爬山了"
  • 用户打开朋友圈:LRANGE feed:user:1001 0 9(获取最新10条动态)。

优势:按时间顺序存储,取最新数据时不用排序,直接用LRANGE分页,性能很高。

3. 栈结构:实现“最近访问”功能

比如“用户最近浏览的商品”,用List的LPUSH(加商品ID)和LTRIM(保留最近N条):

  • 用户浏览商品2001:LPUSH history:user:1001 2001
  • 只保留最近10条:LTRIM history:user:1001 0 9
  • 查看最近浏览:LRANGE history:user:1001 0 9

原理:每次加新商品到头部,超过10条就截断尾部,保证只存最新数据。

四、Set

Set 是无序且无重复的集合,核心优势是自动去重和高效的集合运算(交集、并集、差集),查询元素是否存在的时间复杂度是O(1)。

1. 抽奖系统

把所有参与用户的ID存入Set,利用Set的随机操作实现抽奖:

  • 初始化奖池:SADD lottery:1001 user:1001 user:1002 user:1003
  • 不允许重复中奖:SPOP lottery:1001(随机删除并返回一个用户ID,抽中后从奖池移除);
  • 允许重复中奖:SRANDMEMBER lottery:1001(随机返回一个用户ID,不删除,可重复抽)。

优势:自动去重,不用手动判断用户是否已参与,随机操作高效。

2. 白名单/黑名单

用Set存储白名单用户ID,判断用户是否在白名单时用SISMEMBER

  • 加入白名单:SADD whitelist:admin user:2001 user:2002

  • 校验身份:SISMEMBER whitelist:admin user:2001(返回1表示在白名单,0表示不在)。

优势:O(1)查询速度,比查数据库或用List遍历快得多,适合高频校验场景。

3. 点赞功能

以帖子或朋友圈 ID 为 key,点赞用户 ID 为 value 存入 Set:

  • 用户1001给动态5001点赞:SADD like:feed:5001 user:1001
  • 用户取消点赞:SREM like:feed:5001 user:1001
  • 判断用户是否点赞:SISMEMBER like:feed:5001 user:1001
  • 统计点赞数:SCARD like:feed:5001

优势:自动去重,不用担心用户重复点赞,统计和判断都高效。

4. 集合运算:共同好友/共同兴趣

比如存好友关系时,以用户 ID 为 key,好友 ID 为 value 存入 Set,求两个用户 Set 的交集就能得到共同好友;

存用户兴趣标签时,以用户 ID 为 key,兴趣标签为 value 存入 Set,求不同用户 Set 的交集,就能计算共同兴趣。

利用Set的交集(SINTER)、并集(SUNION)实现社交场景的匹配:

  • 存储好友关系:用户1001的好友存set:friend:1001,用户1002的好友存set:friend:1002
  • 查共同好友:SINTER set:friend:1001 set:friend:1002(返回两个用户都有的好友ID);
  • 兴趣匹配:用户1001的兴趣存set:tag:1001(比如“篮球、电影”),用户1002的兴趣存set:tag:1002,用SINTER查共同兴趣。

五、ZSet

ZSet 有序且无重复,每个元素有一个 score 用于排序,适合需要排序的场景。

1. 排行榜

积分排行榜、步数排行榜,以积分为 score,用户 ID 为 value 存入 ZSet,按分数排序:

  • 用户1001积分为800:ZADD rank:score 800 user:1001
  • 用户积分增加:ZINCRBY rank:score 100 user:1001(积分加100,变成900);
  • 查Top10(从高到低):ZREVRANGE rank:score 0 9 WITHSCORES(WITHSCORES表示返回分数);
  • 查用户排名:ZREVRANK rank:score user:1001(返回排名,0表示第1名)。

优势:自动排序,不用手动维护排名,查询TopN性能极高。

2. 滑动窗口限流

比如“每个IP每分钟最多访问120次”,用ZSet的分数存“请求时间戳”,元素存“请求ID”(或随机值):

  • 每次请求时,先删除“1分钟前的旧请求”:ZREMRANGEBYSCORE limit:ip:192.168.1.1 0 (当前时间戳-60000)
  • 统计当前窗口内的请求数:ZCARD limit:ip:192.168.1.1
  • 若请求数<120,就把当前请求加入ZSet:ZADD limit:ip:192.168.1.1 当前时间戳 请求ID:xxx
  • 若请求数≥120,拒绝请求。

优势:精准控制“任意1分钟内”的请求量,解决计数器限流的“临界问题”。

3. 浏览记录

以用户 ID 为 key,时间戳为 score,帖子/商品 ID 为 member 存入 ZSet,可按时间范围快速做分页查询。

和List的“最近访问”类似,但ZSet能按时间戳(分数)更灵活地筛选:

  • 用户1001浏览商品2001(时间戳1690000000):ZADD history:user:1001 1690000000 goods:2001
  • 查看“今天内的浏览记录”:ZREVRANGEBYSCORE history:user:1001 (当前时间戳) (当前时间戳-86400000) WITHSCORES
  • 只保留最近100条:ZREMRANGEBYRANK history:user:1001 100 -1(删除排名100以后的记录)。

优势:支持按时间范围筛选,比List的分页更灵活。

4. 在线用户列表

以用户活跃时间戳为 score,用户 ID 为 value 存入 ZSet,能实现按登录时间排序、查询在线用户、强制下线等功能。

用ZSet的分数存“用户最后活跃时间戳”,元素存用户ID:

  • 用户1001登录/操作:ZADD online:user 1690000000 user:1001(更新活跃时间戳);
  • 筛选“5分钟内活跃的用户”:ZREVRANGEBYSCORE online:user (当前时间戳) (当前时间戳-300000)
  • 清理“30分钟未活跃的用户”:ZREMRANGEBYSCORE online:user 0 (当前时间戳-1800000)

优势:能快速筛选活跃用户,实现“按登录时间排序”“踢下线”等功能。

补充:Stream

如果用List做消息队列满足不了需求(比如需要持久化、多消费者),可以用Redis 5.0+新增的Stream结构:

  • 支持“消息持久化”:消息存在磁盘,Redis宕机后不会丢失;
  • 支持“消费者组”:多个消费者可以组成一个组,共同消费一个队列,避免重复消费;
  • 支持“ACK确认”:消费者处理完消息后发送ACK,未ACK的消息会重新分配,保证消息不丢失。

场景:中小系统不想引入RabbitMQ、Kafka等重量级MQ,用Stream做异步通信(比如订单回调、日志收集)完全够用。

http://www.dtcms.com/a/434617.html

相关文章:

  • Vue 与 React 深度对比:技术差异、选型建议与未来趋势
  • 创意网站页面wordpress预约小程序
  • Android_framework-odex优化
  • RAG核心特性:文档过滤和检索
  • 26.awk 使用手册
  • AI应用开发新范式:从模型API到交互式网页的极速实现路径
  • 网站建设2017主流代码语言太原百度快照优化排名
  • Python学习之day02学习(函数模块的上传、数据类型+)
  • 可以下载的建站网站河南省建设厅门户网站
  • [创业之路-661]:采集狩猎社会的主要技术、技术产业链以及产要产品
  • 做图文的网站传媒公司名字大全免费
  • 网站开发和游戏开发哪个好网站怎么架设
  • HttpEntity 详解
  • win11电脑设备和打印机中的设备栏,计算机图标有黄色感叹号
  • 做外贸有那些网站平台校园网站策划书
  • 建网站签合同微营销平台系统
  • Go 语言核心知识点
  • Vue 中‘$‘符号含义
  • OSPF协议详解2:链路状态通告(LSA)与邻居关系建立
  • hot100做题整理(11-20)
  • IDEA自动构建与热部署配置
  • 国庆day2
  • Mac添加全局变量
  • 东方美学融合真空保鲜技术,海信璀璨真空头等舱650冰箱发布
  • 网站设计风格分析牡丹江到林口火车时刻表
  • 【操作系统】外存到cpu数据流动路径
  • logits和softmax分布
  • 硬件工程师入门基础知识(九)压敏电阻
  • [Linux]学习笔记系列 -- lib/xarray.c eXtensible Array (XArray) 可扩展数组
  • 基于物理信息神经网络(PINN)求解二维稳态对流-扩散方程的MATLAB实现