SpringBoot秒杀项目三(页面优化)

1.页面缓存

为了防止服务器瞬间访问量较大,我们将页面缓存至redis中,redis缓存的过期时间设置为60s,比较短。页面缓存时间不能太长,因为如果太长的话,页面数据发生 变化缓存是不会及时更新的。

    @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.getGoodsList, "", String.class);
    	if(!StringUtils.isEmpty(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.isEmpty(html)) {
    		redisService.set(GoodsKey.getGoodsList, "", html);
    	}
    	return html;
    }

对to_list页面进行压测,结果如下:
在这里插入图片描述
QPS能够达到5471了,相比于没有加页面缓存之前QPS提升了2000左右

2.对象缓存

  • 将从数据库中查询到的User信息缓存到redis中。 (Id, user) ,对象缓存没有设置过期时间
  • 更新密码:先查询user是否存在。如果存在就先更新数据库,再删除缓存(id, user),更新缓存(token, user)。这样就不会出现数据库和缓存不一致的现象了

可以先更新缓存,再更新数据库吗?
这种方式是不可以的,会存在一定问题,如果缓存删除了过后,另外一个线程读取了数据库中的旧数据,就会导致缓存不一致。

	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;
	}
	// http://blog.csdn.net/tTU1EvLDeLFq5btqiK/article/details/78693323
	public boolean updatePassword(String token, long id, String formPass) {
		//取user
		MiaoshaUser user = getById(id);
		if(user == null) {
			throw new GlobalException(CodeMsg.MOBILE_NOT_EXIST);
		}
		//更新数据库
		MiaoshaUser toBeUpdate = new MiaoshaUser();
		toBeUpdate.setId(id);
		toBeUpdate.setPassword(MD5Util.formPassToDBPass(formPass, user.getSalt()));
		miaoshaUserDao.update(toBeUpdate);
		//处理缓存
		redisService.delete(MiaoshaUserKey.getById, ""+id);
		user.setPassword(toBeUpdate.getPassword());
		redisService.set(MiaoshaUserKey.token, token, user);
		return true;
	}

2.页面静态化,前后端分离

将页面直接缓存到用户的浏览器,提升效应速度。

所有前端页面都是HTML,通过JS、Ajax来访问服务端拿到数据渲染页面。如果只做页面缓存,那么客户端仍然需要到服务端下载页面数据,有了页面静态化之后,这样浏览器就可以将HTML缓存到客户端,页面数据就不需要重复下载了,只需要下载动态的数据就可以了

之前将后端数据放入Model中,前端使用thymeleaf模块来获取后端数据。静态化其实就是采用html+ajax的方式

解决超卖问题方法:
(1)优化查询语句

	@Update("update miaosha_goods set stock_count = stock_count - 1 where goods_id = #{goodsId} and stock_count > 0")
	public int reduceStock(MiaoshaGoods g);

(2)添加唯一索引
就是分表,秒杀的订单和正常的订单是两张表,在数据库中建立用户id和商品id的唯一索引,防止用户插入重复的记录。每次插入的时候,索引不能重复就不能插入,因为写了事务的注解 就会回滚。这样就可以防止重复秒杀

你可能感兴趣的:(SSM秒杀系统)