java商城秒杀

流程

登录/注册——>列表——>详情页——>秒杀

优化

html等静态资源不需要重新到服务器获取,cdn会缓存。在做倒计时时,超过时间禁用按钮,或者已经点击过按钮禁用按钮,按钮绑定一次点击事件,保证只发送一次请求

只需要获取服务器时间保证时间一致,服务器时间接口不需要优化,获取时间接口简单并发量很高效率足够

获取秒杀地址接口:可以用redis,redis官方并发可以到10万,集群化后可以高达百万
在获取地址时,先到redis查看,如果没有再到mysql获取并保存到redis,下次访问就能直接在redis访问,当mysql更新时可以主动更新redis

秒杀接口:不可用缓存,涉及库存增减会导致数据不一致.使用mysql的事务保证数据一致

其他方案

通过redis/nosql实现一个原子计数器,计算库存,保证数据的原子性,同时产生的行为信息通过分布式MQ发布记录。后端通过取出MQ里的消息消费,落地到mysql
在这里插入图片描述
缺点:需要大量的运维成本去维护分布式的NOSQL和MQ组件的稳定性
开发成本:保持nosql中数据一致,当减库存失败时数据回滚等等
很难解决重复秒杀,需要记录消息再次发送消息去确认。不适合新手

为什么mysql低效

单执行update语句,一秒可以达到4w并发
在我们开发中需要使用事务去保证数据一致,一个用户秒杀的流程是:减库存——>新增秒杀记录,因为使用的是事务,一个事务开始会锁住当前要修改的行记录,直到事务完成或者回滚,在一个用户的事务还未完成时其他用户只能等待,导致mysql效率降低。
update,insert,commit过程中存在网络延迟,java客户端中需要GC,导致mysql性能下降。

总结

方法一:
1.前端控制,按钮控制防止重复,暴露接口
2.动静态数据分离:CDN缓存后端缓存
3.事务竞争:减少锁时间
行级锁在事务commit或者rollback之后释放,优化可以往如何减少行级锁持有时间方向,
3.1.修改mysql源码,当update条数是一条时自动commit。
3.2.存储过程,mysql完成整个事务,减少GC干扰和网络延迟

方法二:
1.使用缓存存储当前商品秒杀状态
2.select当前用户状态和订单状态防止重复秒杀
3.使用mq消息队列延迟消费信息

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
java实现秒杀系统@Controller @RequestMapping("seckill")//url:/模块/资源/{id}/细分 /seckill/list public class SeckillController { private final Logger logger = LoggerFactory.getLogger(this.getClass()); @Autowired private SeckillService seckillService; @RequestMapping(value="/list",method = RequestMethod.GET) public String list(Model model){ //获取列表页 List list=seckillService.getSeckillList(); model.addAttribute("list",list); //list.jsp+model = ModelAndView return "list";//WEB-INF/jsp/"list".jsp } @RequestMapping(value = "/{seckillId}/detail",method = RequestMethod.GET) public String detail(@PathVariable("seckillId") Long seckillId, Model model){ if (seckillId == null){ return "redirect:/seckill/list"; } Seckill seckill = seckillService.getById(seckillId); if (seckill == null){ return "forward:/seckill/list"; } model.addAttribute("seckill",seckill); return "detail"; } //ajax json @RequestMapping(value = "/{seckillId}/exposer", method = RequestMethod.POST, produces = {"application/json;charset=UTF-8"}) @ResponseBody public SeckillResult exposer(@PathVariable("seckillId") Long seckillId){ SeckillResult result; try { Exposer exposer =seckillService.exportSeckillUrl(seckillId); result = new SeckillResult(true,exposer); } catch (Exception e) { logger.error(e.getMessage(),e); result = new SeckillResult(false,e.getMessage()); } return result; } @RequestMapping(value = "/{seckillId}/{md5}/execution", method = RequestMethod.POST, produces = {"application/json;charset=UTF-8"} ) @ResponseBody public SeckillResult execute(@PathVariable("seckillId")Long seckillId,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值