Redis学习笔记-秒杀活动中Redis的作用

文章目录

  • Redis学习笔记-秒杀活动中Redis的作用
      • 1.笔记图
      • 2.秒杀活动三阶段
      • 3.秒杀对Redis的两个要求
      • 4.高并发下Redis如何库存信息的正确
      • 5.和高并发相关的处理

Redis学习笔记-秒杀活动中Redis的作用

1.笔记图

Redis学习笔记-秒杀活动中Redis的作用_第1张图片

2.秒杀活动三阶段

  • 秒杀活动前
  • 用户会不断刷新商品详情页,这会导致详情页的瞬时请求量剧增
  • 把商品详情页的页面元素静态化,然后使用 CDN 或是浏览器把这些静态化的元素缓存起来
  • 秒杀活动开始
  • 大量用户点击商品详情页上的秒杀按钮,会产生大量的并发请求查询库存
  • 为了支撑大量高并发的库存查验请求,我们需要在这个环节使用 Redis 保存库存量
  • 订单处理可以在数据库中执行,但库存扣减不能交给数据库处理
    • 订单处理会涉及支付、商品出库、物流等多个关联操作,这些操作本身涉及数据库中的多张数据表,要保证处理的事务性,需要在数据库中完成
    • 需要直接在 Redis 中进行库存扣减,一旦库存有余量,我们就立即在 Redis 中扣减库存
  • 杀活动结束后
  • 可能还会有部分用户刷新商品详情页,尝试等待有其他用户退单
  • 已经成功下单的用户会刷新订单详情,跟踪订单的进展
  • 这个阶段中的用户请求量已经下降很多了,服务器端一般都能支撑

3.秒杀对Redis的两个要求

  • 支持高并发
  • Redis 本身高速处理请求的特性就可以支持高并发
  • 如有多个秒杀商品,可以使用切片集群,不同的实例保存不同商品的库存,避免所有的秒杀请求都集中在一个实例上
  • 保证库存查验和库存扣减原子性执行:使用 Redis 的原子操作或是分布式锁这两个功能特性

4.高并发下Redis如何库存信息的正确

  • 基于原子操作支撑秒杀场景
  • 对应两个信息,分别是总库存量和已秒杀量,可以使用一个 Hash 类型的键值对来保存库存的这两个信息
key: itemID
value: {total: N, ordered: M}

Tips:itemID 是商品的编号,total 是总库存量,ordered 是已秒杀量

  • 使用 Redis 的原子操作
  • 使用 Lua 脚本原子性地执行这两个操作
  • lua脚本内容
#获取商品库存信息            
local counts = redis.call("HMGET", KEYS[1], "total", "ordered");
#将总库存转换为数值
local total = tonumber(counts[1])
#将已被秒杀的库存转换为数值
local ordered = tonumber(counts[2])  
#如果当前请求的库存量加上已被秒杀的库存量仍然小于总库存量,就可以更新库存         
if ordered + k <= total then
    #更新已秒杀的库存量
    redis.call("HINCRBY",KEYS[1],"ordered",k)                              return k;  
end               
return 0
  • 基于分布式锁来支撑秒杀场景
  • 先让客户端向 Redis 申请分布式锁,只有拿到锁的客户端才能执行库存查验和库存扣减
  • 大量的秒杀请求会在争夺分布式锁时被过滤掉
  • 库存查验和扣减不需要使用原子操作,多个并发客户端只有一个客户端能够拿到锁,已经保证了客户端并发访问的互斥性
  • 伪代码
//使用商品ID作为key
key = itemID
//使用客户端唯一标识作为value
val = clientUniqueID
//申请分布式锁,Timeout是超时时间
lock =acquireLock(key, val, Timeout)
//当拿到锁后,才能进行库存查验和扣减
if(lock == True) {
   //库存查验和扣减
   availStock = DECR(key, k)
   //库存已经扣减完了,释放锁,返回秒杀失败
   if (availStock < 0) {
      releaseLock(key, val)
      return error
   }
   //库存扣减成功,释放锁
   else{
     releaseLock(key, val)
     //订单处理
   }
}
//没有拿到锁,直接返回
else
   return

5.和高并发相关的处理

  • 前端静态页面的设计:秒杀页面上能静态化处理的页面元素,我们都要尽量静态化,这样可以充分利用 CDN 或浏览器缓存服务秒杀开始前的请求
  • 请求拦截和流控:在秒杀系统的接入层,对恶意请求进行拦截,避免对系统的恶意攻击,例如使用黑名单禁止恶意 IP 进行访问。如果 Redis 实例的访问压力过大,为了避免实例崩溃,我们也需要在接入层进行限流,控制进入秒杀系统的请求数量
  • 库存信息过期时间处理Redis 中保存的库存信息其实是数据库的缓存,为了避免缓存击穿问题,我们不要给库存信息设置过期时间
  • 数据库订单异常处理:如果数据库没能成功处理订单,可以增加订单重试功能,保证订单最终能被成功处理

Tips:小建议:秒杀活动带来的请求流量巨大,我们需要把秒杀商品的库存信息用单独的实例保存,而不要和日常业务系统的数据保存在同一个实例上,这样可以避免干扰业务系统的正常运行

扫码关注
在这里插入图片描述

你可能感兴趣的:(Redis,redis,分布式,缓存,数据库,nosql)