电商抢购高并发JAVA简单实现
假设场景如下:
库存20瓶茅台53°。
页面发起100万次请求抢购20瓶茅台,用Jmeter测试工具模拟。
要求100万次请求全部得到及时响应,抢购到或者抢购不到。
单机springboot内嵌tomcat,系统服务正常运行,不宕机。
库存不能产生超卖,数据库的库存不能出问题。
Demo设计思路:
1 限流 每秒只放5个请求,其他请求直接返回:本次未抢购到。不走后续业务逻辑。
2 缓存 每次用户请求茅台的剩余库存数时,查询jvm缓存中的剩余数量。
说白了,上谷歌的guava包做。maven依赖引入
<dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>18.0</version>
</dependency>
mysql表设计
1 用户购买记录表
CREATE TABLE `buy_goods` (
`buyer` varchar(255) DEFAULT NULL,
`sku_name` varchar(255) DEFAULT NULL,
`buydate` datetime DEFAULT NULL,
`amout` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2 库存信息表
CREATE TABLE `sku_stock` (
`sku_name` varchar(255) DEFAULT NULL,
`avaliable_amout` bigint(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
插入20瓶茅台的一条记录。
INSERT INTO `demoa`.`sku_stock` (`sku_name`, `avaliable_amout`) VALUES ('maotai', '20');
springboot程序。
BuyDao.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dao.IBuyDao"><!--查询单个--><insert id="insertBuyGoods">INSERT INTO buy_goods (`buyer`,`sku_name`,`buydate`,`amout`)VALUES(#{param1},#{param2},sysdate(),#{param3})</insert><select id="querySkuAmout" parameterType="java.lang.String" resultType="java.lang.Long">SELECTavaliable_amoutFROMsku_stockWHEREsku_name =#{param1}</select><update id="updateSkuAmout">update sku_stockset avaliable_amout=avaliable_amout-#{param2}where sku_name =#{param1}</update></mapper>
IBuyDao接口:
package com.dao;public interface IBuyDao {int insertBuyGoods(String buyer,String skuname,int amout);long querySkuAmout(String skuname);int updateSkuAmout(String skuname,int reduceAmount);
}
BuyDemo。Controller:
package com;import com.dao.IBuyDao;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.RateLimiter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;@RestController
@Slf4j
public class BuyDemo {@ResourceIBuyDao buyDao;final AtomicLong atomicLong=new AtomicLong(0);final AtomicInteger atomicInteger=new AtomicInteger(0);public static final SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");//流控速率,每秒放行5个请求。final RateLimiter rateLimiter=RateLimiter.create(5);//guava_cache本地缓存,JVM级别缓存volatile LoadingCache<String, Long> Cache_AvaliableAmout = CacheBuilder.newBuilder()//设置cache的初始大小为10,要合理设置该值.initialCapacity(10)//设置并发数为3,即同一时间最多只能有3个线程往cache执行写入操作.concurrencyLevel(3)//设置cache中的数据在写入之后的存活时间为10秒.expireAfterWrite(10, TimeUnit.SECONDS)//构建cache实例.build(new CacheLoader<String, Long>() {@Overridepublic Long load(String skuName) throws Exception {long amout= buyDao.querySkuAmout(skuName);log.info("查询数据库:"+skuName+"可用数量为:"+amout);return amout;}});@RequestMapping("/buygoods")@ResponseBodypublic String buygoods(String skuName) {//是否能通过流控,true表示该请求通过流控,可以请求后台业务,false表示该请求被流控,无法请求业务,直接被返回未抢购到boolean get=rateLimiter.tryAcquire();//被流控,抢购失败if(!get){return "buying maotai is too hot,wait later "+atomicLong.incrementAndGet();}try {//商品卖完了,直接返回无货。if(Cache_AvaliableAmout.get(skuName)<=0){return "no avaliable sku "+atomicLong.incrementAndGet();}//简单的锁机制synchronized (this){//double-check防止过量超卖if(Cache_AvaliableAmout.get(skuName)<=0){return "no avaliable sku "+atomicLong.incrementAndGet();}//更新库存数量,插入购买者的购买记录。buyDao.updateSkuAmout(skuName,1);buyDao.insertBuyGoods(UUID.randomUUID().toString(),skuName,1);//刷新缓存Cache_AvaliableAmout.refresh(skuName);log.info(simpleDateFormat.format(new Date())+" buy one "+atomicInteger.incrementAndGet());}return "buy success";} catch (Exception e) {e.printStackTrace();return "system error";}}
}
Jmeter测试信息:
点击运行后:
Jemter输出信息:
Jmeter一百万请求全部完成。
后续因为无货,请求不走mysql,请求秒回。
前期有货,抢购到需要走sql查询和更新,所以有点耗时,几百毫秒。
idea控制台输出信息:
2021-05-16 20:53:20.657 INFO 23664 --- [http-nio-8900-exec-88] com.BuyDemo : 查询数据库:maotai可用数量为:20
2021-05-16 20:53:20.680 INFO 23664 --- [http-nio-8900-exec-88] com.BuyDemo : 查询数据库:maotai可用数量为:19
2021-05-16 20:53:20.722 INFO 23664 --- [http-nio-8900-exec-88] com.BuyDemo : 2021-05-16 20:53:20.722 buy one 1
2021-05-16 20:53:20.753 INFO 23664 --- [http-nio-8900-exec-130] com.BuyDemo : 查询数据库:maotai可用数量为:18
2021-05-16 20:53:20.843 INFO 23664 --- [http-nio-8900-exec-130] com.BuyDemo : 2021-05-16 20:53:20.753 buy one 2
2021-05-16 20:53:20.861 INFO 23664 --- [http-nio-8900-exec-66] com.BuyDemo : 查询数据库:maotai可用数量为:17
2021-05-16 20:53:20.862 INFO 23664 --- [http-nio-8900-exec-66] com.BuyDemo : 2021-05-16 20:53:20.862 buy one 3
2021-05-16 20:53:20.882 INFO 23664 --- [http-nio-8900-exec-41] com.BuyDemo : 查询数据库:maotai可用数量为:16
2021-05-16 20:53:20.883 INFO 23664 --- [http-nio-8900-exec-41] com.BuyDemo : 2021-05-16 20:53:20.883 buy one 4
2021-05-16 20:53:20.899 INFO 23664 --- [http-nio-8900-exec-102] com.BuyDemo : 查询数据库:maotai可用数量为:15
2021-05-16 20:53:20.900 INFO 23664 --- [http-nio-8900-exec-102] com.BuyDemo : 2021-05-16 20:53:20.899 buy one 5
2021-05-16 20:53:20.922 INFO 23664 --- [http-nio-8900-exec-65] com.BuyDemo : 查询数据库:maotai可用数量为:14
2021-05-16 20:53:20.922 INFO 23664 --- [http-nio-8900-exec-65] com.BuyDemo : 2021-05-16 20:53:20.922 buy one 6
2021-05-16 20:53:20.941 INFO 23664 --- [http-nio-8900-exec-181] com.BuyDemo : 查询数据库:maotai可用数量为:13
2021-05-16 20:53:20.941 INFO 23664 --- [http-nio-8900-exec-181] com.BuyDemo : 2021-05-16 20:53:20.941 buy one 7
2021-05-16 20:53:20.961 INFO 23664 --- [http-nio-8900-exec-97] com.BuyDemo : 查询数据库:maotai可用数量为:12
2021-05-16 20:53:20.962 INFO 23664 --- [http-nio-8900-exec-97] com.BuyDemo : 2021-05-16 20:53:20.962 buy one 8
2021-05-16 20:53:21.181 INFO 23664 --- [http-nio-8900-exec-119] com.BuyDemo : 查询数据库:maotai可用数量为:11
2021-05-16 20:53:21.182 INFO 23664 --- [http-nio-8900-exec-119] com.BuyDemo : 2021-05-16 20:53:21.182 buy one 9
2021-05-16 20:53:21.194 INFO 23664 --- [http-nio-8900-exec-113] com.BuyDemo : 查询数据库:maotai可用数量为:10
2021-05-16 20:53:21.195 INFO 23664 --- [http-nio-8900-exec-113] com.BuyDemo : 2021-05-16 20:53:21.194 buy one 10
2021-05-16 20:53:21.209 INFO 23664 --- [http-nio-8900-exec-61] com.BuyDemo : 查询数据库:maotai可用数量为:9
2021-05-16 20:53:21.210 INFO 23664 --- [http-nio-8900-exec-61] com.BuyDemo : 2021-05-16 20:53:21.210 buy one 11
2021-05-16 20:53:21.225 INFO 23664 --- [http-nio-8900-exec-115] com.BuyDemo : 查询数据库:maotai可用数量为:8
2021-05-16 20:53:21.225 INFO 23664 --- [http-nio-8900-exec-115] com.BuyDemo : 2021-05-16 20:53:21.225 buy one 12
2021-05-16 20:53:21.251 INFO 23664 --- [http-nio-8900-exec-98] com.BuyDemo : 查询数据库:maotai可用数量为:7
2021-05-16 20:53:21.253 INFO 23664 --- [http-nio-8900-exec-98] com.BuyDemo : 2021-05-16 20:53:21.253 buy one 13
2021-05-16 20:53:21.267 INFO 23664 --- [http-nio-8900-exec-94] com.BuyDemo : 查询数据库:maotai可用数量为:6
2021-05-16 20:53:21.268 INFO 23664 --- [http-nio-8900-exec-94] com.BuyDemo : 2021-05-16 20:53:21.268 buy one 14
2021-05-16 20:53:21.285 INFO 23664 --- [http-nio-8900-exec-116] com.BuyDemo : 查询数据库:maotai可用数量为:5
2021-05-16 20:53:21.286 INFO 23664 --- [http-nio-8900-exec-116] com.BuyDemo : 2021-05-16 20:53:21.286 buy one 15
2021-05-16 20:53:21.299 INFO 23664 --- [http-nio-8900-exec-147] com.BuyDemo : 查询数据库:maotai可用数量为:4
2021-05-16 20:53:21.300 INFO 23664 --- [http-nio-8900-exec-147] com.BuyDemo : 2021-05-16 20:53:21.300 buy one 16
2021-05-16 20:53:21.315 INFO 23664 --- [http-nio-8900-exec-38] com.BuyDemo : 查询数据库:maotai可用数量为:3
2021-05-16 20:53:21.315 INFO 23664 --- [http-nio-8900-exec-38] com.BuyDemo : 2021-05-16 20:53:21.315 buy one 17
2021-05-16 20:53:21.335 INFO 23664 --- [http-nio-8900-exec-20] com.BuyDemo : 查询数据库:maotai可用数量为:2
2021-05-16 20:53:21.335 INFO 23664 --- [http-nio-8900-exec-20] com.BuyDemo : 2021-05-16 20:53:21.335 buy one 18
2021-05-16 20:53:21.515 INFO 23664 --- [http-nio-8900-exec-3] com.BuyDemo : 查询数据库:maotai可用数量为:1
2021-05-16 20:53:21.516 INFO 23664 --- [http-nio-8900-exec-3] com.BuyDemo : 2021-05-16 20:53:21.516 buy one 19
2021-05-16 20:53:21.711 INFO 23664 --- [http-nio-8900-exec-159] com.BuyDemo : 查询数据库:maotai可用数量为:0
2021-05-16 20:53:21.712 INFO 23664 --- [http-nio-8900-exec-159] com.BuyDemo : 2021-05-16 20:53:21.712 buy one 20
2021-05-16 20:53:31.915 INFO 23664 --- [http-nio-8900-exec-127] com.BuyDemo : 查询数据库:maotai可用数量为:0
2021-05-16 20:53:42.101 INFO 23664 --- [http-nio-8900-exec-191] com.BuyDemo : 查询数据库:maotai可用数量为:0
2021-05-16 20:53:52.300 INFO 23664 --- [http-nio-8900-exec-117] com.BuyDemo : 查询数据库:maotai可用数量为:0
mysql表信息:
1 库存表茅台卖为0
2 用户购买记录表,共有20条购买记录
电商抢购高并发JAVA简单实现相关推荐
- Java生鲜电商平台-高并发核心技术订单与库存实战
Java生鲜电商平台-高并发核心技术订单与库存实战 一. 问题 一件商品只有100个库存,现在有1000或者更多的用户来购买,每个用户计划同时购买1个到几个不等商品. 如何保证库存在高并发的场景下是安 ...
- 电商平台 高并发 微服务 方案_Java生鲜电商平台-秒杀系统微服务架构设计与源码解析实战...
Java生鲜电商平台- 什么是秒杀 通俗一点讲就是网络商家为促销等目的组织的网上限时抢购活动 比如说京东秒杀,就是一种定时定量秒杀,在规定的时间内,无论商品是否秒杀完毕,该场次的秒杀活动都会结束.这种 ...
- php秒杀防重复中奖_PHP如何应对秒杀抢购高并发思路
原标题:PHP如何应对秒杀抢购高并发思路 我们常用QPS(Query Per Second,每秒处理请求数)来衡量一个web应用的吞吐率,解决每秒数万次的高并发场景,这个指标非常关键. 举个栗子:假设 ...
- 电商抢购秒杀系统的设计_1_应用场景分析
2019独角兽企业重金招聘Python工程师标准>>> 电商抢购秒杀系统的设计_1_应用场景分析 概述 所谓知已知彼,百战不殆,在开始详细介绍实战中的抢购秒杀系统时,我们了解一些抢购 ...
- java设计模式并发_[高并发Java 七] 并发设计模式
[高并发Java 七] 并发设计模式 [高并发Java 七] 并发设计模式 为什么80%的码农都做不了架构师?>>> 在软件工程中,设计模式(design pattern)是对软件设 ...
- 谷粒商城电商项目 高可用集群篇
更多视频,JAVA收徒 QQ:987115885谷粒商城电商项目 高可用集群篇339.k8s-简介.mp4340.k8s-架构原理&核心概念.mp4341.k8s-集群搭建-环境准备.mp43 ...
- JAVA毕设项目社区电商平台系统(java+VUE+Mybatis+Maven+Mysql)
JAVA毕设项目社区电商平台系统(java+VUE+Mybatis+Maven+Mysql) 项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX(Web ...
- ssm毕设项目木棉堂水果电商平台1r83i(java+VUE+Mybatis+Maven+Mysql+sprnig)
ssm毕设项目木棉堂水果电商平台1r83i(java+VUE+Mybatis+Maven+Mysql+sprnig) 项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + H ...
- 电商项目的并发量一般是多少_【高并发】高并发秒杀系统架构解密,不是所有的秒杀都是秒杀!...
写在前面 很多小伙伴反馈说,高并发专题学了那么久,但是,在真正做项目时,仍然不知道如何下手处理高并发业务场景!甚至很多小伙伴仍然停留在只是简单的提供接口(CRUD)阶段,不知道学习的并发知识如何运用到 ...
最新文章
- 30个实用的Python脚本(请收藏)
- CP20常见问题解答
- photoshop是用什么编程语言开发的_为什么中国开发不出流行的操作系统和编程语言?...
- oracle execute immediate执行多条语句_用数据库的方式思考SQL是如何执行的
- postgreSQL数据库默认用户postgres常用命令
- gitlab 删除分支_idea gitlab 分支 pull、push 实践笔记
- Microsoft SQL Server 2005简体中文开发版下载
- Win10设置热点IP
- 用计算机玩吃鸡,W10电脑系统玩吃鸡游戏会卡顿怎么办
- 35岁以后的Android程序员出路在哪里?大牛最佳总结
- centos7.6 桌面版本 网卡重启失败 记录
- Android 5.0 CardView 应用
- 显示器预算有限,是买1080P 144HZ还是买2K 60HZ?
- 财务管理都学什么计算机课程,财务管理都学什么课程
- edu教育邮箱申请注册资讯平台是什么?
- 隐马尔科夫模型(HMM)及其扩展
- 机器学习之机器学习绪论-王而川-专题视频课程
- 公路水运工程安全电子光盘_公路水运工程施工安全标准化.pdf
- 商标的商品和服务分类有45个
- 语法格式描述规范BNF、EBNF、ABNF