高并发秒杀系统设计_第1页
高并发秒杀系统设计_第2页
高并发秒杀系统设计_第3页
高并发秒杀系统设计_第4页
高并发秒杀系统设计_第5页
已阅读5页,还剩6页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、 高并发秒杀系统设计架构文摘 微信号 ArchDigest功能介绍 每天一篇架构领域重磅好文,涉及一线互联网公司的互联网应用架构、大数据、机器学习等各个热门领域。功能需求:设计一个秒杀系统初始方案商品表设计:热销商品提供给用户秒杀,有初始库存。Entitypublic class SecKillGoods implements Serializable Id private String id; /* * 剩余库存 */ private Integer remainNum; /* * 秒杀商品名称 */ private String goodsName;秒杀订单表设计:记录秒杀成功的订单情况E

2、ntitypublic class SecKillOrder implements Serializable Id GenericGenerator(name = PKUUID, strategy = uuid2) GeneratedValue(generator = PKUUID) Column(length = 36) private String id; /用户名称 private String consumer; /秒杀产品编号 private String goodsId; /购买数量 private Integer num;Dao设计:主要就是一个减少库存方法,其他CRUD使用JP

3、A自带的方法public interface SecKillGoodsDao extends JpaRepository Query(update SecKillGoods g set g.remainNum = g.remainNum - ?2 where g.id=?1) Modifying(clearAutomatically = true) Transactional int reduceStock(String id,Integer remainNum);数据初始化以及提供保存订单的操作:Servicepublic class SecKillService Autowired Sec

4、KillGoodsDao secKillGoodsDao; Autowired SecKillOrderDao secKillOrderDao; /* * 程序启动时: * 初始化秒杀商品,清空订单数据 */ PostConstruct public void initSecKillEntity() secKillGoodsDao.deleteAll(); secKillOrderDao.deleteAll(); SecKillGoods secKillGoods = new SecKillGoods(); secKillGoods.setId(123456); secKillGoods.se

5、tGoodsName(秒杀产品); secKillGoods.setRemainNum(10); secKillGoodsDao.save(secKillGoods); /* * 购买成功,保存订单 * param consumer * param goodsId * param num */ public void generateOrder(String consumer, String goodsId, Integer num) secKillOrderDao.save(new SecKillOrder(consumer,goodsId,num); 下面就是controller层的设计C

6、ontrollerpublic class SecKillController Autowired SecKillGoodsDao secKillGoodsDao; Autowired SecKillService secKillService; /* * 普通写法 * param consumer * param goodsId * return */ RequestMapping(/seckill.html) ResponseBody public String SecKill(String consumer,String goodsId,Integer num) throws Inter

7、ruptedException /查找出用户要买的商品 SecKillGoods goods = secKillGoodsDao.findOne(goodsId); /如果有这么多库存 if(goods.getRemainNum()=num) /模拟网络延时 Thread.sleep(1000); /先减去库存 secKillGoodsDao.reduceStock(num); /保存订单 secKillService.generateOrder(consumer,goodsId,num); return 购买成功; return 购买失败,库存不足; 上面是全部的基础准备,下面使用一个单元测

8、试方法,模拟高并发下,很多人来购买同一个热门商品的情况。Controllerpublic class SecKillSimulationOpController final String takeOrderUrl = :8080/seckill.html; /* * 模拟并发下单 */ RequestMapping(/simulationCocurrentTakeOrder) ResponseBody public String simulationCocurrentTakeOrder() /httpClient工厂 final SimpleClientHttpRequestFactory h

9、ttpRequestFactory = new SimpleClientHttpRequestFactory(); /开50个线程模拟并发秒杀下单 for (int i = 0; i 50; i+) /购买人姓名 final String consumerName = consumer + i; new Thread(new Runnable() Override public void run() ClientHttpRequest request = null; try URI uri = new URI(takeOrderUrl + ?consumer=consumer + consum

10、erName + &goodsId=123456&num=1); request = httpRequestFactory.createRequest(uri, HttpMethod.POST); InputStream body = request.execute().getBody(); BufferedReader br = new BufferedReader(new InputStreamReader(body); String line = ; String result = ; while (line = br.readLine() != null) result += line

11、;/获得页面内容或返回内容 System.out.println(consumerName+:+result); catch (Exception e) e.printStackTrace(); ).start(); return simulationCocurrentTakeOrder; 访问localhost:8080/simulationCocurrentTakeOrder,就可以测试了 预期情况:因为我们只对秒杀商品(123456)初始化了10件,理想情况当然是库存减少到0,订单表也只有10条记录。实际情况:订单表记录 商品表记录 下面分析一下为啥会出现超库存的情况:因为多个请求访问,

12、仅仅是使用dao查询了一次数据库有没有库存,但是比较恶劣的情况是很多人都查到了有库存,这个时候因为程序处理的延迟,没有及时的减少库存,那就出现了脏读。如何在设计上避免呢?最笨的方法是对SecKillController的seckill方法做同步,每次只有一个人能下单。但是太影响性能了,下单变成了同步操作。RequestMapping(/seckill.html)ResponseBodypublic synchronized String SecKill改进方案根据多线程编程的规范,提倡对共享资源加锁,在最有可能出现并发争抢的情况下加同步块的思想。应该同一时刻只有一个线程去减少库存。但是这里给出

13、一个最好的方案,就是利用Oracle,Mysql的行级锁同一时间只有一个线程能够操作同一行记录,对SecKillGoodsDao进行改造:public interface SecKillGoodsDao extends JpaRepository Query(update SecKillGoods g set g.remainNum = g.remainNum - ?2 where g.id=?1 and g.remainNum0) Modifying(clearAutomatically = true) Transactional int reduceStock(String id,Inte

14、ger remainNum);仅仅是加了一个and,却造成了很大的改变,返回int值代表的是影响的行数,对应到controller做出相应的判断。RequestMapping(/seckill.html) ResponseBody public String SecKill(String consumer,String goodsId,Integer num) throws InterruptedException /查找出用户要买的商品 SecKillGoods goods = secKillGoodsDao.findOne(goodsId); /如果有这么多库存 if(goods.getRemainNum()=num) /模拟网络延时 Thread.sleep(1000); if(goods.getRemainNum()0) /先减去库存 int i = secKi

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论