秒杀系统中的页面优化

秒杀系统中,并发的瓶颈在数据库,如何有效的减少对数据库的访问呢?最有效的方法就是加缓存,页面静态化、前后端分离、


1.页面缓存

什么是页面缓存呢,就是我们在访问页面时,不是直接让系统帮我们渲染页面,而是去缓存中去取,如果找到了就直接返回给客户端,如果没有我们就手动渲染模板,返回给客户端的同时,将结果缓存到如redis之类的缓存中,以便下次使用。这里我们使用Redis来缓存。

以前,我们直接将动态数据存入model中,然后返回HTML页面,通过SpringMVC来帮我们渲染

@RequestMapping(value="/to_list")
public String list( Model model,User user) {
    model.addAttribute("user", user);
    List<GoodsVo> goodsList = goodsService.listGoodsVo();
    model.addAttribute("goodsList", goodsList);
    return "goods_list";
}

缓存就是,我们直接返回HTML的源代码,将HTML源代码存在redis中,通过手动渲染来返回页面。 (这里的模板语言使用的是Thymeleaf)

@RequestMapping(value="/to_list", produces="text/html")
@ResponseBody
public String list(HttpServletRequest request, HttpServletResponse response, Model model,MiaoshaUser user) {
    model.addAttribute("user", user);
    List<GoodsVo> goodsList = goodsService.listGoodsVo();
    model.addAttribute("goodsList", goodsList);

    //1.取缓存,看缓存中是否存在以有的缓存
    String html = redisService.get(GoodsKey.getGoodsList, "", String.class);
    if(!StringUtils.isEmpty(html)) {
        return html;
    }

    //2.如果是空的,我们就手动渲染
    //通过SpringWebContext取出动态数据
    SpringWebContext ctx = new SpringWebContext(request,response,
                request.getServletContext(),request.getLocale(), model.asMap(), applicationContext );
    //手动用thymeleaf的模板引擎来渲染
    html = thymeleafViewResolver.getTemplateEngine().process("goods_list", ctx);
    //存入redis中
    if(!StringUtils.isEmpty(html)) {
        redisService.set(GoodsKey.getGoodsList, "", html);
    }

    return html;
}

但是你需要控制好缓存的有效时间,来保证页面的及时性。我这里设置的是60秒,对于大多数人来说,看到的页面是60秒之前的并无大碍。也可以设置更短的时间来保证更高的及时性。


2.对象缓存

对象缓存是更细粒度的缓存。

我们还是拿使用缓存之前和使用缓存之后的两个代码块来进行比较,下面是一个普通的通过userId从数据库中取用户。

public User getById(long id) {
    return userDao.getById(id);
}

为了减少对数据库的读写,我们可以加一个缓存,先查看缓存中是否存在user信息,没有再去数据库中读取。

public User getById(long id) {
    //1.取缓存 现在redis中看是否存在该user 没有的话就去数据库中取
    MiaoshaUser user = redisService.get(MiaoshaUserKey.getById, ""+id, MiaoshaUser.class);
    if(user != null) {
        return user;
    }

    //2.取数据库  从数据库中取出后,记得要加到缓存中去
    user = miaoshaUserDao.getById(id);
    if(user != null) {
        redisService.set(MiaoshaUserKey.getById, ""+id, user);
    }
        return user;
}

如果我们需要修改用户信息的话,也要修改缓存中对应的用户信息。

public boolean updatePassword(String token, long id, String formPass) {
    //取user
    User user = getById(id);
    if(user == null) {
        throw new GlobalException(CodeMsg.MOBILE_NOT_EXIST);
    }
    //更新数据库
    User toBeUpdate = new User();
    toBeUpdate.setId(id);
    toBeUpdate.setPassword(MD5Util.formPassToDBPass(formPass, user.getSalt()));
    userDao.updateUser(toBeUpdate);
    //处理缓存
    redisService.delete(UserKey.getById, ""+id);
    user.setPassword(toBeUpdate.getPassword());
    redisService.set(UserKey.token, token, user);
    return true;
}

将页面和对象加了缓存之后,QPS从1267翻倍到 2884. 可见网站的性能翻了一倍,就因为减少了对MySQL的访问。


3.页面静态化

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值