秒杀-页面缓存 ,对象缓存,秒杀超买问题
1,页面缓存:缓存时间比较短,适合短时间内变化不大的数据,如查询商品列表的页面以及商品详情添加缓存

@RequestMapping(value="/to_list",produces = "text/html") @ResponseBody public String list(HttpServletRequest request, HttpServletResponse response,Model model, MiaoshaUser user) { model.addAttribute("user", user); // 取缓存 String html = redisService.get(GoodsKey.getByList, "", String.class); if(StringUtils.isNotEmpty(html)){ return html; } List<GoodsVo> goodsList = goodsService.listGoodsVo(); model.addAttribute("goodsList", goodsList); // return "goods_list"; SpringWebContext ctx = new SpringWebContext(request,response, request.getServletContext(),request.getLocale(), model.asMap(), applicationContext ); //手动渲染 html = thymeleafViewResolver.getTemplateEngine().process("goods_list", ctx); if(StringUtils.isNotEmpty(html)){ redisService.set(GoodsKey.getByList,"",html); } return html; }View Code
SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

@RequestMapping(value = "/to_detail/{goodsId}",produces = "text/html") @ResponseBody public String detail(HttpServletRequest request, HttpServletResponse response,Model model,MiaoshaUser user, @PathVariable("goodsId")long goodsId) { model.addAttribute("user", user); // 取缓存 String html = redisService.get(GoodsKey.getByGoodsDetail, ""+goodsId, String.class); if(StringUtils.isNotEmpty(html)){ return html; } GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId); model.addAttribute("goods", goods); long startAt = goods.getStartDate().getTime(); long endAt = goods.getEndDate().getTime(); long now = System.currentTimeMillis(); int miaoshaStatus = 0; int remainSeconds = 0; if(now < startAt ) {//秒杀还没开始,倒计时 miaoshaStatus = 0; remainSeconds = (int)((startAt - now )/1000); }else if(now > endAt){//秒杀已经结束 miaoshaStatus = 2; remainSeconds = -1; }else {//秒杀进行中 miaoshaStatus = 1; remainSeconds = 0; } model.addAttribute("miaoshaStatus", miaoshaStatus); model.addAttribute("remainSeconds", remainSeconds); SpringWebContext sc= new SpringWebContext(request,response,request.getServletContext(),request.getLocale(),model.asMap(),applicationContext); //手动渲染 html = thymeleafViewResolver.getTemplateEngine().process("goods_detail", sc); if(StringUtils.isNotEmpty(html)){ redisService.set(GoodsKey.getByGoodsDetail,""+goodsId,html); } return html; }View Code
2.对象缓存,把时间设置成永久(0),

public MiaoshaUser getById(long id) { //取缓存 MiaoshaUser user = redisService.get(MiaoshaUserKey.getById, "" + id, MiaoshaUser.class); if(user!=null){ return user; } user = miaoshaUserDao.getById(id); if(user!=null){ redisService.set(MiaoshaUserKey.getById,""+id,user); } return user; }View Code
但是在有数据更新的时候要注意缓存的更新问题,否则会出现缓存不一致的现象,必须先更新数据库,再更新缓存,顺序不可以颠倒,否则容易出现数据不一致的问题

public boolean updatePassword(String token,long id, String formPass){ //获取user MiaoshaUser user = redisService.get(MiaoshaUserKey.getById, "" + id, MiaoshaUser.class); if(user==null){ throw new GlobalException(CodeMsg.MOBILE_NOT_EXIST); } MiaoshaUser miaoshaUser=new MiaoshaUser(); miaoshaUser.setPassword(MD5Util.formPassToDBPass(formPass,user.getSalt())); miaoshaUser.setId(id); miaoshaUserDao.update(miaoshaUser); //更新缓存 redisService.delete(MiaoshaUserKey.getById,""+id); user.setPassword(miaoshaUser.getPassword()); redisService.set(MiaoshaUserKey.token,token,user); return true; }View Code
3.秒杀前先判断是否还有库存,其次判断是否已经秒杀到,再减库存“update miaosha_goods set stock_count=stock_count-1 where goods_id=#{goodsId} and stock_count>0”

@RequestMapping(value="/do_miaosha", method=RequestMethod.POST) @ResponseBody public Result<OrderInfo> miaosha(Model model,MiaoshaUser user, @RequestParam("goodsId")long goodsId) { model.addAttribute("user", user); if(user == null) { return Result.error(CodeMsg.SESSION_ERROR); } //判断库存 GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);//10个商品,req1 req2 int stock = goods.getStockCount(); if(stock <= 0) { return Result.error(CodeMsg.MIAO_SHA_OVER); } //判断是否已经秒杀到了 MiaoshaOrder order = orderService.getMiaoshaOrderByUserIdGoodsId(user.getId(), goodsId); if(order != null) { return Result.error(CodeMsg.REPEATE_MIAOSHA); } //减库存 下订单 写入秒杀订单 OrderInfo orderInfo = miaoshaService.miaosha(user, goods); return Result.success(orderInfo); }View Code

更多精彩