页面缓存
防止瞬间的访问
首先去缓存中取,找到直接返回,没有就渲染返回,在缓存
比如商品列表,访问的话是 goods_list 模板
将数据放到 model中然后去渲染模板
改为 直接返回 html
先创建一个对商品的前缀,用于存入 redis中
GoodsKey设置,设置默认缓存。60s
public class GoodsKey extends BasePrefix {
private GoodsKey(int exprieSeconds,String prefix) {
super( exprieSeconds,prefix);
}
public static GoodsKey getGoodsList = new GoodsKey(60,"gl");
}
控制器请求商品列表
@Autowired
ThymeleafViewResolver thymeleafViewResolver;
@Autowired
ApplicationContext applicationContext;
@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;
}
URL缓存
商品详情也修改为URL缓存,也就是页面缓存多个参数。
@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.getGoodsDetail, ""+goodsId, String.class);
if(!StringUtils.isEmpty(html)) {
return html;
}
//手动渲染
GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
System.out.println("秒杀价格: "+goods.getMiaoshaPrice());
model.addAttribute("goods",goods);
//秒杀状态
int miaoshaStatus =0;
//还剩多少秒 -1为结束
int remainSeconds = 0;
//
long startAt = goods.getStartDate().getTime();
long endtAt = goods.getEndDate().getTime();
long now = System.currentTimeMillis();
if(now<startAt){//秒杀没开始
miaoshaStatus = 0;
remainSeconds = (int)(startAt-now)/1000;
}else if (now>endtAt) {//秒杀结束
miaoshaStatus = 2;
remainSeconds = -1;
}else {//秒杀进行中
miaoshaStatus = 1;
remainSeconds = 0;
}
model.addAttribute("miaoshaStatus",miaoshaStatus);
model.addAttribute("remainSeconds",remainSeconds);
SpringWebContext ctx = new SpringWebContext(request,response,
request.getServletContext(),request.getLocale(), model.asMap(), applicationContext );
html = thymeleafViewResolver.getTemplateEngine().process("goods_detail", ctx);
if(!StringUtils.isEmpty(html)) {
redisService.set(GoodsKey.getGoodsDetail, ""+goodsId, html);
}
return html;
}
不同页面的不同 goods_id
redisService.set(GoodsKey.getGoodsDetail, ""+goodsId, html);
对象缓存
之前利用 token将用户实体对应的存入到了redis中
还有个方法是根据用户手机号号来重复数据库中查询用户
改为从redis缓存中取出来
public MiaoshaUser getByMobile(String mobile) {
//取缓存
MiaoshaUser user = redisService.get(MiaoshaUserKey.getByMobile,mobile,MiaoshaUser.class);
if (user!=null) {
//return miaoshaUserDao.getByMobile(mobile);
return user;
}else {
//查不到就去数据库中查询
user = miaoshaUserDao.getByMobile(mobile);
if (user!=null){
redisService.set(MiaoshaUserKey.getByMobile,mobile,user);
}
return user;
}
}
如果有对用户的更新,
先利用上面的查询,如果是空格的直接 抛出异常,
找到了就 存入数据库并删除对象缓存,更新 token(新创建一个实体,传入要改的属性,sql修改)
尽量少修改数据。
页面静态化
2.优点:利用浏览器的缓存
前后端分离
就是后端只写接口,返回json数据就可以了。
这个就比较熟悉了
spring-boot配置静态资源缓存
自动给静态资源Response添加缓存头Cache-Control和Expires值
不会再从服务器中请求,利用了浏览器缓存。
#static
spring.resources.add-mappings=true
spring.resources.cache-period= 3600 //配置缓存多少秒
spring.resources.chain.cache=true
spring.resources.chain.enabled=true
spring.resources.chain.gzipped=true
spring.resources.chain.html-application-cache=true
spring.resources.static-locations=classpath:/static/
如何防止一个用户秒杀一个商品多次(卖超)
对秒杀订单表建一个索引是 用户id和商品id。
每次插入的时候,索引不能重复就不能插入,因为写了事务的注解
就会回滚。
还可以将订单插入到缓存中。
静态资源优化
1.JS/CSS压缩,减少流量
2.多个JS/CSS组合到一个请求,减少连接数
engine,在Nginx的基础上添加。
还有 wbpack 前端打包的。
都可以使用。
3.CDN
并发大的瓶颈在数据库,利用缓存,redis缓存和浏览器缓存,Nginx也可以加缓存