基于redis实现秒杀并防止超卖

news2024/12/24 20:40:25

基于redis实现秒杀并防止超卖

  • 为什么基于redis
  • 针对秒杀商品库存为一个的情况
    • setnx
    • 代码实现
    • 测试
  • 针对有多个库存的商品

为什么基于redis

因为所有redis的操作(这里指的是key的操作,像备份落盘之类的另算)都是单线程的,所以是线程安全的,但是有一点需要注意,这里线程安全仅仅指的是单个操作,如果有连续性的操作,需要使用lua脚本来保证原子性。

针对秒杀商品库存为一个的情况

比如抢单个红包,类似于美团的抢单等多个用户争抢一个资源的情况,这时我们可以使用redis分布式锁来实现比如 setnx。

setnx

setnx:向Redis中添加一个key,只用当key不存在的时候才添加并返回1,存在则不添加返回0。并且这个命令是原子性的。
使用setnx作为分布式锁时,添加成功表示获取到锁,添加失败表示未获取到锁。至于添加的value值无所谓可以是任意值(根据业务需求),只要保证多个线程使用的是同一个key,所以多个线程添加时只会有一个线程添加成功,就只会有一个线程能够获取到锁。而释放锁锁只需要将锁删除即可。

代码实现

@Service
public class SecKillServiceImpl implements SecKillService {

    private final JedisUtils jedisUtils;

    private final String SecKillKey = "goods_";

    public SecKillServiceImpl(JedisUtils jedisUtils) {
        this.jedisUtils = jedisUtils;
    }

    @Override
    public boolean doSecKill(String userId, String goodsId) {
        Jedis jedis = jedisUtils.getJedis();
        Long result = jedis.setnx(SecKillKey + goodsId, userId);
        if (result == 1) {
            jedis.expire(SecKillKey + goodsId, 5000);
            jedis.close();
            // TODO:写业务逻辑即可
            return true;
        }
        jedis.close();
        return false;
    }
}

测试

使用jmetter模拟5000并发测试结果,仅有一个抢到了该商品其他全部失败。
在这里插入图片描述

针对有多个库存的商品

大家可以想一下上边实现方式对于多个库存的商品是否适用,其实答案很简单,是不太适用的,针对多个库存的商品,不能使用类似于分布式锁的方式,因为该种方式同时只能由一个用户争抢到资源,只有等找个用户完成了下单动作释放掉锁之后其他用户才可以继续进行,所以秒杀效率特别底下。

所以可以采用redis的递减来实现,当秒杀开始的时候我们提前将秒杀商品的库存加载到redis,用户秒杀的时候采用递减来判断是否抢到了库存。

实现

    @Override
    public boolean doComplexSecKill(String userId, String goodsId) {
        Jedis jedis = jedisUtils.getJedis();
        Long result = jedis.decrBy(SecKillKey + goodsId, 1);
        if (result > 0) {
            jedis.close();
            return true;
        }
        jedis.close();
        return false;
    }

测试

首先redis先预热库存100

![在这里插入图片描述](https://img-blog.csdnimg.cn/ba75ead0274e48b8bff2c424f6c6b26c.png
jmetter模拟10000个用户去抢这100个商品
在这里插入图片描述
仅有100个用户抢到了资源

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/623784.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一文读懂:LoRA实现大模型LLM微调

LoRA大模型LLM微调 为什么要进行微调?LoRA思路提高权重更新效率选择低的秩 实现LoRALoRA在LLaMA实现 为什么要进行微调? 在快速发展的人工智能领域中,以高效和有效的方式使用大型语言模型变得越来越重要。 预训练的大型语言模型通常被称为优…

02-启动 Vue 项目

一. 学习目标 掌握 Vue 项目的启动 二. 学习内容 掌握 Vue 项目的启动 三. 学习过程 项目的启动也有两种方式,一种是通过图形界面启动,另一种是通过命令行启动。 1.图形界面 打开vscode编辑器,点击 1.文件 ——>打开文件夹&#xff0c…

springboot实现支付宝支付(沙箱环境)

springboot实现支付宝支付 1. 获取应用id,应用私钥和支付宝公钥2. 开始开发3. 内网穿透4. 测试支付功能 1. 获取应用id,应用私钥和支付宝公钥 进入支付宝控制台:https://open.alipay.com/develop/manage 找到沙箱 这里可以看到应用id 可以看到应用私钥和支付宝公钥,获取这…

Zoho:集成ChatGPT、开发大型语言模型,加紧布局AI+SaaS

在企业的数字化转型进程中,管理层和员工的数字化意识会随着建设的推进而不断提高,对于办公场景的数字化应用需求也不断产生。传统的办公系统建设中,系统的应用能力需要支撑越来越丰富的场景需求。 《今日人工智能》采访到Zoho中国VP兼SaaS事业…

【编程语言 · C语言 · for语句】

for 语句 C语言中,使用for语句也可以控制一个循环,并且在每一次循环时修改循环变量。在循环语句中,for语句的应用最为灵活,不仅可以用循环次数已经确定的情况,而且可以用于循环次数不确定而只给出循环结束条件的情况。…

jenkins构建pipline无法执行shell命令原因

问题表现 新的服务器上,新安装的jenkins,在上面创建了一个pipline项目,脚本里有shell命令,但是jenkins每次执行都卡住,经过尝试,无论多简单的命令都执行不了,cp,mv等都不行&#xf…

华为路由器:ospf协议三张表及邻居建立过程

说明:本篇接上一篇继续讲解 拓扑图 为了方便,我把R1/2/3/4/5的router id改成了回环网卡的IP。 ospf协议三张表 邻居表(neighbortable) OSPF用邻居机制来发现和维持路由的存在,邻居表存储了双向通信的邻居关系OSPF路…

矩形图:数据之美在图形中展现

在当今信息爆炸的时代,数据已经成为决策和洞察的重要基石,但海量的数据如果不经过整理和呈现,往往难以得出有意义的结论。这时候,可视化工具的作用就变得尤为重要了。在众多可视化形式中,矩形图以其简洁直观的特点受到…

团队管理之性能实施团队日志9

最近项目进入胶着状态。 混合场景在有些项目组里已经可以开始了,但还是有两三个项目组现在是完全没办法混合起来的。 本周计划是把基准测试、容量测试跑完,稳定性测试每个项目组至少能跑一遍。 但是从进度上来看,容量测试至少有四个系统不能跑…

各类动态路由协议汇总简介

目录 一、前言 二、OSPF协议 (一)OSPF是什么 (二)OSPF的工作原理 (三)OSPF的特点 (四)OSPF的使用 (五)OSPF的优点 (六)总结 …

ROS——从深度图转换到octomap(C++)

文章目录 介绍环境准备三维灰度栅格图三维RGB栅格图对点云进行过滤处理参考介绍 八叉树是用于在3D视觉中细分空间的数据结构。每个立方体都可以逐级地细分为8个子立方体,直到达到了给定的最小体积(体素)尺寸。且该最小体积(体素)决定了八叉树的分辨率。 octomap的作用:…

代码随想录算法训练营第五十一天|309.最佳买卖股票时机含冷冻期|714.买卖股票的最佳时机含手续费

LeetCode309.最佳买卖股票时机含冷冻期 动态规划五部曲: 1,确定dp数组以及下标的含义:dp[i][j],第i天状态为j,所剩的最多现金为dp[i][j]。出现冷冻期之后,状态其实是比较复杂度,例如今天买入股…

接口自动化【七】__包装响应结果的数据为key-value

文章目录 前言 一、本章学习的思路 二、用接口新建商品_使用步骤 ​​​​​​​步骤一:先用抓包的方式拿到新建商品的接口 步骤二:我们先用单接口的形式,把这个商品添加成功 三、处理响应接口_(包装响应结果的数据为&#xf…

Flume自定义拦截器 - ETL拦截器和分类拦截器

水善利万物而不争,处众人之所恶,故几于道💦 目录 一、拦截器(Interceptor)和选择器(Selector) 拦截器(Interceptor) 选择器(Selector) 二、自定…

【机器学习 | 深度学习】Colab是什么?以及如何使用它?

文章目录 一、介绍二、如何使用 Colaboratory 创建代码三、实例测试 一、介绍 Colaboratory(简称为Colab)是由Google开发的一种基于云端的交互式笔记本环境。它提供了免费的计算资源(包括CPU、GPU和TPU),可让用户在浏…

本地部署gitlab学习git使用

文章目录 前言一、安装gitlab二、nginx反向代理三、本地配置hosts,自定义域名四、配置gitlab独立ngxin实现域名访问五、其他总结 前言 最近想学习git使用了,在本地部署一个gitlab社区版玩玩吧~ gitlab只能部署在liunx系统上面,可以使用云服务…

TLD2314EL-ASEMI代理英飞凌汽车芯片TLD2314EL

编辑:ll TLD2314EL-ASEMI代理英飞凌汽车芯片TLD2314EL 型号:TLD2314EL 品牌:Infineon(英飞凌) 封装:SSOP-14-EP-150mil 特性:LED驱动、汽车芯片 宽温度范围:-40C~150C 封装:SSOP-14&…

虚拟云网络系列 | 如何将 NSX NVDS 迁移到 VDS

1.NVDS 迁移到 VDS 的主要原因 在早期的 vsphere6.7 的版本上安装 NSX-T 采用的都是 NVDS,而随着 NSX 版本的升级,从 NSX 4.0 开始,NSX 已经不在支持在 ESXi 上部署 NVDS,仅能使用 vsphere7.0 上的 VDS。所以,对于早期…

linux系统编程-----下

linux网络编程 tcp通信 Berkeley Socket TCP/IP协议族标准只规定了网络各个层次的设计和规范,具体实现则需要由各个操作系统厂商完成。最出名的网络库由BSD 4.2版本最先推出,所以称作伯克利套接字,这些API随后被移植到各大操作系统中&…