Redis之秒杀系统
目录
Redis 秒杀
Mysql数据库设计
Mysql秒杀实现
Mysql+Redis秒杀实现
秒杀是一种高并发场景,通常指的是在短时间内(秒级别)有大量用户同时访问某个商品或服务,争相抢购的情景。在这种情况下,系统需要处理大量并发请求,确保公平性、一致性,并防止因并发而导致的问题,例如超卖、恶意请求等。以下是在高并发秒杀场景下需要考虑的一些关键问题和解决方案:
-
超卖问题: 大量用户同时抢购同一商品可能导致超卖(卖出超过库存数量)的问题。为了解决这个问题,可以采用悲观锁或乐观锁的方式来控制库存的访问。数据库的行级锁、分布式锁等技术都可以用来防止超卖。
-
性能优化: 高并发场景下,系统性能是关键。使用缓存、异步处理、CDN 加速等手段可以显著提升系统的性能。缓存可以存储商品信息、用户状态等,减轻数据库压力。异步处理可以将一些不需要即时返回结果的操作异步执行,减轻请求的响应时间。
-
并发控制: 在高并发场景下,为了防止系统崩溃或服务不可用,需要对并发进行控制。可以使用队列、限流等技术,确保系统在承受能力范围内处理请求,防止系统超负荷崩溃。
-
秒杀令牌和时间窗口: 可以在系统中引入秒杀令牌,只有携带有效令牌的用户才能参与秒杀。同时,可以设置一个时间窗口,只在特定的时间范围内允许秒杀操作,有效控制请求的涌入。
-
用户鉴权和防刷: 针对恶意请求,需要进行用户鉴权,并采用防刷策略。例如,限制同一用户在短时间内的请求次数,通过验证码等方式增加用户请求的成本,防止恶意请求。
-
队列和异步处理: 使用消息队列将用户的秒杀请求进行排队,然后异步处理。这样可以有效地削峰填谷,减轻系统瞬时的压力,提高系统的容错能力。
-
分布式事务: 如果系统是分布式的,需要考虑分布式事务的问题。确保在秒杀过程中的各个阶段,包括扣减库存、生成订单等,能够保持事务的一致性。
-
实时监控和日志记录: 在高并发场景下,实时监控是及时发现问题、解决问题的关键。记录详细的日志信息,包括用户请求日志、系统性能日志等,便于事后分析和优化。
Redis 秒杀
Mysql数据库设计
/*
SQLyog Community v11.26 (32 bit)
MySQL - 8.0.33 : Database - test
*********************************************************************
*//*!40101 SET NAMES utf8 */;/*!40101 SET SQL_MODE=''*/;/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`test` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */;USE `test`;/*Table structure for table `stock` */DROP TABLE IF EXISTS `stock`;CREATE TABLE `stock` (`id` BIGINT NOT NULL AUTO_INCREMENT,`name` VARCHAR(20) DEFAULT NULL,`count` INT DEFAULT NULL,`create_time` TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;/*Data for the table `stock` */INSERT INTO `stock`(`id`,`name`,`count`,`create_time`) VALUES (1,'apple',500,'2023-11-28 19:02:04'),(2,'huawei',500,'2023-11-28 19:02:26');/*Table structure for table `stock_order` */DROP TABLE IF EXISTS `stock_order`;CREATE TABLE `stock_order` (`id` BIGINT NOT NULL AUTO_INCREMENT,`name` VARCHAR(20) DEFAULT NULL,`price` INT DEFAULT NULL,`create_time` TIMESTAMP NULL DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1729467951815541250 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;/*Data for the table `stock_order` *//*Table structure for table `article_select` */DROP TABLE IF EXISTS `article_select`;/*!50001 DROP VIEW IF EXISTS `article_select` */;
/*!50001 DROP TABLE IF EXISTS `article_select` */;/*!50001 CREATE TABLE `article_select`(`a` bigint ,`b` varchar(11) ,`c` varchar(20) ,`d` bigint
)*/;/*View structure for view article_select *//*!50001 DROP TABLE IF EXISTS `article_select` */;
/*!50001 DROP VIEW IF EXISTS `article_select` */;/*!50001 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `article_select` (`a`,`b`,`c`,`d`) AS select `article`.`id` AS `id`,`article`.`name` AS `name`,`article`.`des` AS `des`,`article`.`categoryid` AS `categoryid` from `article` */;/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
Mysql秒杀实现
秒杀代码设计初步代码如下:
@RestController
public class MyController {@AutowiredStockMapper stockMapper;@AutowiredStockOrderMapper stockOrderMapper;@Transactional@GetMapping("/order/{id}")public String order(@PathVariable("id") Long id){Stock stock = stockMapper.selectById(id);Integer count = stock.getCount();if(count<=0){throw new RuntimeException("库存不足");}StockOrder stockOrder=new StockOrder();stockOrder.setName(stock.getName());stockOrderMapper.insert(stockOrder);UpdateWrapper<Stock> updateWrapper=new UpdateWrapper<>();updateWrapper.setSql("count = count - 1 where count > 0 and id ="+id); //在mysql这里执行的时候,数据库会加行锁,所以相对是安全的int update = stockMapper.update(null, updateWrapper);if(update<=0){throw new RuntimeException("库存不足");}return "success";}
}
由于业务代码直接与mysql数据库进行交互,mysql一秒支持的并发量低,性能较低,然后下面进行压测:

压测得到的汇总报告如下图:

Mysql+Redis秒杀实现
使用redis修改代码如下:
@RestController
public class MyController {@AutowiredStringRedisTemplate stringRedisTemplate;@AutowiredStockMapper stockMapper;@AutowiredStockOrderMapper stockOrderMapper;@PostConstructpublic void init(){List<Stock> stocks = stockMapper.selectList(null);for (Stock stock : stocks) {stringRedisTemplate.opsForValue().set("product_"+stock.getId(),stock.getCount()+"");}}@GetMapping("/order/{id}")public String order(@PathVariable("id") Long id){Long decrement = stringRedisTemplate.opsForValue().decrement("product_" + id);if(decrement<0){stringRedisTemplate.opsForValue().increment("product_"+id);return "库存不足";}try {((MyController)AopContext.currentProxy()).mys_order(id);}catch (Exception e){stringRedisTemplate.opsForValue().increment("product_"+id);return "库存不足";}return "购买成功";}@Transactionalpublic void mys_order(Long id){Stock stock = stockMapper.selectById(id);if(stock.getCount()<=0){throw new RuntimeException("库存不足");}StockOrder stockOrder=new StockOrder();stockOrder.setName(stock.getName());stockOrderMapper.insert(stockOrder);UpdateWrapper<Stock> updateWrapper=new UpdateWrapper<>();updateWrapper.setSql("count = count - 1 where count > 0 and id ="+id); //在mysql这里执行的时候,数据库会加行锁,所以相对是安全的int update = stockMapper.update(null, updateWrapper);if(update<=0){throw new RuntimeException("库存不足");}}
}
压测结果吞吐量如下图,使用redis作为缓存相对于仅仅使用mysql数据库吞吐量提升了不少,性能得到了提升。

相关文章:
Redis之秒杀系统
目录 Redis 秒杀 Mysql数据库设计 Mysql秒杀实现 MysqlRedis秒杀实现 秒杀是一种高并发场景,通常指的是在短时间内(秒级别)有大量用户同时访问某个商品或服务,争相抢购的情景。在这种情况下,系统需要处理大量并发请…...
c++基础----new
c基础----new 在C中,new是一个运算符,用于动态分配内存并返回指向该内存的指针。它可以用于创建单个对象、数组以及动态分配的对象。 下面是new的几种常见用法: 动态分配单个对象: int* ptr new int; // 动态分配一个int类型…...
Java中的mysql——面试题+答案(存储过程,外键,隔离级别,性能优化)——第23期
当涉及MySQL时,面试题的范围可以涵盖数据库设计、优化、复制、分片等方面。 什么是数据库范式?为什么要遵循数据库范式? 答案: 数据库范式是一组规范,用于设计关系数据库表的结构,以减少数据冗余和提高数据…...
一种新的基于物理的AlGaN/GaN HFET紧凑模型
标题:A new physics-based compact model for AlGaN/GaN HFETs (IEEE MTT-S International Microwave Symposium) 摘要 摘要 - 针对AlGaN/GaN HFET,提出了一种无拟合参数的物理解析模型。对于非饱和操作,建立了两个接入区和栅极下方I-V特性的…...
uniapp基础-教程之HBuilderX基础常识篇02
uniapp创建项目时属性多为vue后缀;其中每个文件中都包含了三段式结构分别是template;script;style形势,分别是前端显示的画面以及js和css样式。 template:说大白话就是给别人看的,我们打开页面就可以看到的…...
如何源码编译seaTunnel
如何源码编译seaTunnel 参考Set Up Develop Environment 编译前准备 下列软件需要提前安装好 GitJava ( JDK8/JDK11) 并设置JAVA_HOME 环境变量Scala (只支持 scala 2.11.12 )JetBrains IDEA . 下载源码并编译 git clone gitgithub.com:apache/seatunnel.git cd seatunne…...
msng病毒分析
这是一个非常古老的文件夹病毒,使用XP系统的文件夹图标,采用VB语言开发,使用了一种自定义的壳来保护,会打开网址http://www.OpenClose.ir,通过软盘、U盘和共享目录进行传播,会在U盘所有的目录下生成自身的副本…...
Unity安装
DAY1 下载Unity 打开Unity3D官网,下载Unity Hub,管理Unity的软件。链接https://unity.cn/releases (可能需要注册账号,就正常注册登录即可) 如果是新版的hub,可能长下面这个样子,还是英文的,点击圆圈的设…...
【代洋集团特惠好物:80瓦太阳能折叠包】
为您的绿色出行保驾护航!代洋集团倾情推出80瓦太阳能折叠包,为您的户外活动提供清洁、便捷的电力支持。 这款太阳能折叠包采用高效能太阳能板,可折叠设计方便携带,轻松为您解决户外用电问题。80瓦的强大功率,让您在户…...
一致性Hash算法
Hash算法 哈希算法将任意长度的二进制值映射为较短的固定长度的二进制值,这个小的二进制值称为哈希值。哈希值是一段数据唯一且极其紧凑的数值表示形式。 Hash算法在安全加密领域MD5、SHA等加密算法,数据存储和查找的Hash表等方面均有应用。Hash表的数…...
linux 下如何将/dev/nvme0n1符格式化为空盘符
linux 下如何将/dev/nvme0n1符格式化为空盘符 作者:DPDK开发栏目:公开2023-08-30 03:01254 在Linux下,你可以使用以下步骤将/dev/nvme0n1硬盘格式化为空盘符: 首先,确保你拥有适当的权限。以管理员或root用户身份登录…...
IP地址的最后一位不可以为0或255
说明 通常情况下,IP 地址的最后一位不能为 0 或 255。这是因为这些特定的 IP 地址有特殊用途。 IP 地址的最后一位为 0 通常用作网络地址,表示整个网络的起始地址。IP 地址的最后一位为 255 通常用作广播地址,用于将数据包发送到同一网络中…...
代洋集团:太阳能智能座椅,创新能源的未来篇章
在代洋集团,我们致力于打造一个更绿色,更智能的未来。我们的太阳能智能座椅,就是我们对这一承诺的最新体现。 太阳能智能座椅,一种将绿色能源与智能化完美结合的产品。它利用高效的太阳能电池板,捕获并转化阳光为电能…...
linux服务器安装gitlab
一、安装gitlab sudo yum install curl policycoreutils-python openssh-server openssh-clients sudo systemctl enable sshd sudo systemctl start sshd sudo firewall-cmd --permanent --add-servicehttp curl https://packages.gitlab.com/install/repositories/gitla…...
Tlog SpringBoot3.x版本无法正常打印TraceId等数据
问题:Springboot3.0版本使用Tlog(1.5.1版本)开源框架时无法打印指定参数 原因:在Java EE 8及更高版本中,javax.servlet.*包已经替换成了jakarta.servlet.*,但是tlog官方只更新到了1.5.1版本所以还没支持到…...
基于Spring原生框架构建原生Spring的第一个程序!
😉😉 学习交流群: ✅✅1:这是孙哥suns给大家的福利! ✨✨2:我们免费分享Netty、Dubbo、k8s、Mybatis、Spring...应用和源码级别的视频资料 🥭🥭3:QQ群:583783…...
[个人笔记] Git的CLI笔录
Git - CLI笔录 Git的CLI笔录 Git - CLI笔录Git的CLI笔录 Git的CLI笔录 origin: 表示远程仓库节点名称。 当有多个远程仓库时 可新增远程仓库节点名称如 new_origin | new_remote origin/HEAD: 表示当前Git仓库默认分支的引用,通常指向origin/master或origin/main g…...
如何运行C/C++程序
一、在线运行C/C 码曰 - 让代码在云端多飞一会:这是一个支持C/C,Java,Python等多种语言的在线编程,编译运行,粘贴分享的平台。你可以在这里输入你的代码,点击运行按钮,就可以看到输出结果。你也…...
HTML中input标签的23种type类型
一、概述 随着html5的出现,input标签新增了多种类型,用以接收各种类型的用户输入。其中传统输入控件有10种,新增输入控件有13种。 二、传统类型 传统输入控件有10种,如下所示 text 定义单行文本输入框 password 定义…...
接口多态与方法多态
作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO 联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬 在上一篇设计山寨版Str…...
IPD的势、道、法、术、器
目录 简介 一、势:为什么 IPD 是必然选择? 二、道:IPD 的底层哲学 三、法与术:从战略到执行的具体路径 四、器:让流程真正落地的工具与组织 不是每家公司都需要全套 IPD,但每家公司都需要 IPD 思维 简…...
《我看见的世界:李飞飞自传》第1-6章阅读笔记:从移民少女到AI教母的“看见“之旅
前言 当我们谈论人工智能时,我们谈论的是算法、数据、算力,是那些冰冷的代码和复杂的模型。但在《我看见的世界:李飞飞自传》中,李飞飞用她独特的视角告诉我们:AI的本质,是人类对"看见"世界的渴望…...
TorchDynamo与TorchInductor:PyTorch编译器生态的完整解析
TorchDynamo与TorchInductor:PyTorch编译器生态的完整解析 【免费下载链接】torchdynamo A Python-level JIT compiler designed to make unmodified PyTorch programs faster. 项目地址: https://gitcode.com/gh_mirrors/to/torchdynamo TorchDynamo 是一个…...
解决方法:庐山派K230接串口没识别到端口问题
一、插入usb转串口工具之前二、插入usb转串口工具之后三、解决方法说明:🔍 核心原因:USB Serial 设备,没有被识别为 COM 口你现在看到的 USB Serial,说明开发板已经正常启动了,USB 也被电脑识别到了&#x…...
Unlock-Music:浏览器中一键解锁加密音乐文件的完整指南
Unlock-Music:浏览器中一键解锁加密音乐文件的完整指南 【免费下载链接】unlock-music 在浏览器中解锁加密的音乐文件。原仓库: 1. https://github.com/unlock-music/unlock-music ;2. https://git.unlock-music.dev/um/web 项目地址: http…...
Cesium动态数据可视化实战:CallbackProperty结合setInterval打造实时运动轨迹
Cesium动态数据可视化实战:CallbackProperty结合setInterval打造实时运动轨迹 在三维地理信息系统中,实时数据可视化一直是开发者面临的挑战之一。想象一下,当我们需要在地球表面追踪一架正在飞行的无人机,或者监控城市中数百辆出…...
Noto字体终极指南:告别“豆腐块“,让全球文字清晰显示
Noto字体终极指南:告别"豆腐块",让全球文字清晰显示 【免费下载链接】noto-fonts Noto fonts, except for CJK and emoji 项目地址: https://gitcode.com/gh_mirrors/no/noto-fonts 在数字世界中,你是否经常看到那些令人困…...
3分钟掌握Topit:Mac窗口置顶终极指南,让多任务处理效率翻倍!
3分钟掌握Topit:Mac窗口置顶终极指南,让多任务处理效率翻倍! 【免费下载链接】Topit Pin any window to the top of your screen / 在Mac上将你的任何窗口强制置顶 项目地址: https://gitcode.com/gh_mirrors/to/Topit 你是否曾经在Ma…...
告别手动分类!用Python+ArcPy批量处理DEM,一键生成坡度坡向等高线报告
用PythonArcPy实现DEM地形分析全自动化:从数据到报告的智能工作流 第一次接手山区风电项目的地形分析任务时,我花了整整三天时间在ArcGIS界面里反复点击同样的按钮——加载DEM、计算坡度坡向、生成等高线、调整分类阈值、导出图片。当第五个区域的报告终…...
别再只用JSON了!用Protobuf给Go微服务接口性能提升10倍(附完整代码)
别再只用JSON了!用Protobuf给Go微服务接口性能提升10倍(附完整代码) 在微服务架构中,接口性能往往是决定系统吞吐量的关键因素。许多开发者习惯性地使用JSON作为数据交换格式,却不知道这可能在无形中成为性能瓶颈。本…...
