秒杀
秒杀会产生一个瞬间的高并发,使用数据库会增加数据库的访问压力,也会降低访问速度,所以我们应该使用缓存,来降低数据库的访问压力;可以看出这里的操作和原来的下单是不一样的:产生的秒杀预订单不会马上写入数据库,会先写入缓存,等用户支付成功时,修改状态,写入数据库
立即抢购-商品详情-支付-选择地址-超时(关闭订单)
一.需求分析:
秒杀的商品有两种限制:库存限制和时间限制
需求:
①:商家进行申请,录入商品数据
②:运营商进行审核
③:秒杀频道展示秒杀商品,点击图片进行商品详情跳转
④:在详情页点击抢购下单,如果没有库存或者时间不符下单失败
⑤:下单成功跳转支付,支付成功在填写地址
⑥:下单5分钟未支付,取消订单,恢复库存
二.代码逻辑
1.秒杀频道的首页
①:增加一个查询正在秒杀的商品(必须是审核通过的和库存大于0的,还有一个条件是开始日期必须小于等于当前日期,截止日期大于等于当前日期)的方法,这个方法会返回一个所有秒杀商品的列表;然后在控制层使用这个方法后端代码就完成了
②:前端调用方法,获取数据,进行首页的商品展示;toFixed:是取几位小数的API,在这里是在展示剩余库存百分比时用到的
③:因为秒杀会引起瞬间的数据库访问的高并发,所以我们可以在查询出秒杀商品列表时,把数据放入缓存,这样只要数据不变访问一次数据库就行了;我们在上面增加的方法上加上缓存:在查询之前判断缓存中有没有缓存的商品数据,没有再进行访问数据库,查询数据,把数据放入缓存;这里需要注意的是我们在缓存中获取了集合之后,要判断集合是不是空的和集合的长度是不是大于0,一定要记得判断集合的长度
④:我们在缓存中放入的数据的格式是:商品ID:商品对象,我们在秒杀首页中用的是商品信息,所以取得集合是商品对象
2.展示商品详细信息(倒计时)
这里的详情信息展示比较简单,没有静态页面,也没有搜索,只是一个sku的信息展示,不过这里多了一个倒计时用来记录秒杀剩余时间
①:商品详细页的数据也是从缓存中取得数据,不过这次和首页的不一样,我们需要把存储的这个数据都拿出来,就是需要商品id和商品对象
③:增加一个方法,这个方法是根据商品的id在缓存中查询商品具体的数据(这个方法可以在findOne的方法上进行修改)
④:前台增加js方法和页面数据调用,进行数据展示
⑤:倒计时功能:因为秒杀是有时间限制的,所以应该在详情页上有一个倒计时;这个倒计时在ajs中是一个服务:$interval,这个服务的方法,时间的单位是毫秒;我们可以在使用这个服务时指定它的间隔时间(基础是毫秒,指定一秒是1000),我们再用一个变量接收这个时间变量,让它每次都减去1,判断如果这个值小于等于0时,停止
$interval(处理函数,间隔时间)
⑥:倒计时时分秒的处理:getTime():把时间转换成long类型
首先计算从结束时间到当前时间的秒数,计算出来的数需要进行Math.floor(取整数)
把秒数换算成时分秒的格式:写一个方法,分别计算天数\小时数\分钟数,注意计算时分秒时,要减去前面计算的秒数
3.秒杀下单
①:增加一个秒杀下单的方法,这个方法首先是查询缓存中的商品,查完之后要进行判断,看商品是不是存在和库存是不是为0
②:减少库存,我们下了一个单就少了一个该秒杀商品,所以我们应该修改库存数量,并且把这个值重新存入缓存中,当库存数为0时,更新数据库,并且删除缓存中的该商品信息
③:存储秒杀订单(存进缓存,不存入数据库)
向缓存中存入订单时,key是用户id(方便用户找到订单),value就是订单对象(在存入之前,设置订单对象的值)
④:秒杀下单的前端不用传递数量(只能买一件)
如果下单成功,提示支付,跳转支付页面
4.秒杀支付
根据之前的支付进行修改
点击立即抢购,在删减库存的同时,还要检查是不是登录,没有登录提示未登录,跳转支付页面,让支付页面出发登录页面,已经登录了就处理订单,跳转支付页面;注意没有登录也不影响后台的删减库存等操作,因为那个就是存在redis里面的预订单
①:从缓存中提取订单数据
提取之后要进行一下判断,判断该订单是不是存在的和订单号是不是一样的
②:修改订单实体的属性
修改支付日期
修改支付状态
设置微信返回的信息
③:将订单存入数据库
使用insert(插入)把订单信息存入数据库
④:清除缓存中的订单
⑤:如果支付超时(支付失败),这时我们就要把订单中的商品还回去
首先是根据用户ID查询缓存中的订单,如果订单不是空的,需要清除缓存
然后就是查询缓存中的秒杀商品,判断商品是不是空的,如果不为空,库存数加1,把这个商品放进缓存中;如果为空,表示这个商品已经被秒没了,我们就要重新new商品对象,重新设置商品的属性,记得把库存数设置为1,再把这个商品对象存进缓存中