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

【Redis】基础3:一些应用场景

文章目录

  • 1. session管理
    • 1.1 手机号登录流程
    • 1.2 session的数据结构设计
      • 1.2.1 一些概念
      • 1.2.2 session数据结构例子
    • 1.3 引入redis来实现共享session
      • 1.3.1 流程
        • 发送验证码短信的流程
        • 验证码登录流程
        • 登录检查流程
      • 1.3.2 要考虑的问题
  • 2. 限时抢购代金券
    • 2.1 业务流程
    • 2.2 代金券表设计
    • 2.3 高并发场景面临的问题
      • 2.3.1 问题
      • 2.3.2 工具
      • 2.3.3 解决方案

1. session管理

1.1 手机号登录流程

  • 发送短信验证码流程:输入手机号 --> 验证手机号合法(否则回到”输入手机号“) --> 生成验证码 --> 保存验证码到session --> 发送验证码短信。

  • 验证码登录流程:输入手机号、验证码 --> 校验验证码(session中的有没有用户提交的验证码) --> 校验通过,以手机号找用户 --> 用户存在,下一步;用户不存在,则创建用户,再下一步 --> 保存用户信息到session。

  • 登录检查流程:请求携带cookie ,从cookie中拿session id --> 根据session id拿session对象,判断用户是否在session中(用户登录过则在seesion中有记录) --> 用户不存在终止请求响应,或者重定向到登录页;用户存在,继续响应,注意要缓存用户信息,方便后续使用。

如果采用单体服务-单线程-多协程的方式来处理请求,那么session是线程的数据,协程共享它。如果考虑负载均衡而使用多个server实例,那么session要在这些服务实例之间共享,此时只能使用redis(在内存,kv,server实例之间共享)。即session是多个server实例之间共享的状态。

1.2 session的数据结构设计

1.2.1 一些概念

什么是web应用的状态:客户端与服务器在多次交互过程中产生的上下文信息,例如用户登录凭证、购物车内容、操作历史等。

为什么需要状态:判断请求之间的关联性。如判断两次请求是否来自同一个用户,判断两次请求是否来自同一客户端。

session的作用:HTTP是无状态协议,因此需要使用session(服务端维护)跟踪用户状态,常见的状态化机制还有Cookie(服务端分发,客户端携带),Token(服务端分发,客户端携带)。

1.2.2 session数据结构例子

session_obj1 = {'user_id': 'abc','phone': '13112341234','expire_time': 1745738823
}
session_obj2 = {'user_id': 'ABC','phone': '13112341234','expire_time': 1745738823
}
session = {'001': session_obj1,'002': session_obj2
}

1.3 引入redis来实现共享session

redis中保存两类数据:每个手机号的申请的验证码;登录成功的用户信息

1.3.1 流程

发送验证码短信的流程

输入手机号 --> 验证手机号合法(否则回到”输入手机号“) --> 生成验证码 --> 保存验证码到redis,注意加过期时间 ( eg, key=phone:13212341234, val=31245 ) --> 发送验证码短信。

验证码登录流程

输入手机号、验证码 --> 校验验证码(redis中,verify_code = GET phone:13212341234, if verify_code == in_verify_code) --> 校验通过,以手机号找用户 --> 用户存在,下一步;用户不存在,则创建用户,再下一步 --> 保存用户信息到redis( 方式一:用户信息序列化为string形式保存,方式二:直接使用hash,key的格式:token:uuid )。

登录检查流程

请求携带cookie ,从cookie中拿token --> 根据token从redis拿用户信息 --> 拿到用户信息,继续响应,注意要缓存用户信息,方便后续使用同时刷新token过期时间,保证只要用户有请求,登录状态就一直保持;没拿到用户信息,终止请求响应,或者重定向到登录页。

1.3.2 要考虑的问题

问题:如果用户登录后,相当长的一段时间访问那些不需要登录认证的页面,则token一直不会被刷新而自动掉线,这是不合理的。

解决:所有路径都执行刷新token的动作(根据请求cookie中的token访问redis,获取用户信息,用线程变量缓存用户信息,刷新token过期时间),在需要登录认证的路径做额外的登录状态检查工作(检查缓存中是否有用户信息,如果没有则终止继续响应或者重定向到登录页;如果有则继续响应)。

2. 限时抢购代金券

2.1 业务流程

基本流程:查询代金券券(by id) --> 检查时效 --> 检查库存 --> 扣减库存 --> 创建代金券订单并返回订单id

一人只能购买一个单限制下的流程:查询代金券券(by id) --> 检查时效,在时效内继续 --> 检查库存,库存充足继续 --> 根据用户id和代金券di检查代金券订单,订单不存在继续 --> 扣减库存 --> 创建代金券订单并返回订单id

2.2 代金券表设计

对象:普通代金券,限时抢购代金券,代金券订单

表设计:

voucher(voucher_id, shop_id, title, sub_title, rules, pay_value, actual_value, type, status, create_time, update_time)

time_lmt_voucher(voucher_id, stock, start_time, end_time, create_time, update_time)

voucher_order(id, user_id, voucher_id, pay_type, status, pay_time, use_time, refund_time, create_time, update_time)

说明:其中,voucher和time_lmt_voucher是一对一关系,time_lmt_voucher是voucher的扩展。

2.3 高并发场景面临的问题

2.3.1 问题

  1. 超卖(库存为负数):扣减库存逻包含两个操作:读库存并判断库存是否充足,假设初始情况下库存为1(记为op1);更新库存为0(记为op2)。线程1执行op1后线程2也执行op1,然后线程1执行op2,库存为0,线程2再执行op2,库存为-1。
  2. 一人一单限制失效:业务逻辑包含两个操作:根据用户id和代金券id查询代金券订单是否存在,假设初始情况下用户没有代金券订单(记为op1);创建新订单(记为op2)。线程1执行op1后,线程2也执行op1,然后线程1执行op2,创建一个订单,线程2再执行op2,又创建了一个订单。
  3. 使用数据库的自增id作为订单id存在风险(如根据订单id差值推测出订单量等),且订单数量可能受限。

2.3.2 工具

乐观锁:线程不安全不一定发生,不加锁,只有在更新数据时才检查数据是否被已经被修改。使用版本号控制,先访问数据得到版本好,更新时比较版本号,版本号一致则更新数据同时更新版本号,版本号不一致则拒绝更新。

悲观锁:线程不安全一定发生,在访问数据前加锁。

2.3.3 解决方案

  1. 超卖(库存为负数):使用CAS(Compare And Set)原则,限制库存更新操作条件,用op1查询的库存结果来限制op2的更新操作,set time_lmt_voucher into stock=stock-1 where stock=1;
  2. 一人一单限制失效:使用互斥锁构建临界区,把op1和op2放进去。单体服务用进程锁,线程锁,协程锁。分布式服务使用分布式锁。
  3. 使用redis做一个全局id生成器(唯一性,高可用,高性能,递增,安全),id(64bits): 时间戳(32bist) + 序列号(32bits)。
http://www.xdnf.cn/news/2696.html

相关文章:

  • TCP协议
  • 2个关键思路,让微课动画场景制作别具一格
  • Fps鬼泣总结:通信——伤害检测
  • 【数据结构】顺序表
  • 伺服电机AB相输出,接入定时器通道,对定时器IO口的速率有何要求【详细分析】
  • 【Unity完整游戏开发案例】从0做一个太空大战游戏
  • MySQL主从同步原理与实践 - Java架构师面试解析
  • 【Python】Matplotlib:立体永生花绘制
  • 单值映射、多值映射
  • Linux:进程间通信->共享内存
  • 开源网络入侵检测与防御系统:Snort
  • 企业私有大模型DeepSeek落地部署该用什么? Ollama还是vLLM
  • PlatformIO 入门学习笔记(一):背景了解
  • 【每天一个知识点】correntropy(相关熵)
  • 08-STM32外部中断
  • el-input限制输入只能是数字 限制input只能输入数字
  • 中国区域250米归一化植被指数数据集(2000-2023)
  • 迅雷精简绿色融合版【高速下载版】12.1.9.2870【11.2.2.1716】【20250426】
  • 树莓派学习专题<10>:使用V4L2驱动获取摄像头数据--申请和管理缓冲区
  • 【PVR】《Adaptive Palm Vein Recognition Method》
  • codeforcesB. Binary Colouring
  • 实人认证开发指南:用API+深度学习构建人证合一系统
  • 【CF】Day45——Codeforces Round 1021 (Div. 2) BC
  • UV工具的安装与使用
  • 2025系统架构师---数据抽象(Data Abstraction)‌与‌面向对象架构风格
  • Android原生开发基础
  • 龙芯远程方案
  • 如何判断对一件事的认知深度?
  • Python+jieba文本分析示例:实现统计《红楼梦》中的人物并生成词云图
  • 人工智能——XGBoost 算法