zoukankan      html  css  js  c++  java
  • 为什么要使用页面缓存技术

    为什么要使用页面缓存技术

    一、总结

    一句话总结:

    系统的瓶颈往往是来自于数据库,我们可以使用缓存来减少对数据库的访问!

    系统都是逐渐演进的,一个系统在运行中必须是根据场景逐渐地提高优化性能。高并发就是对资源的节约的考验,这种考验除了更换优秀和先进的技术,优化架构,还在于从小处出发,对尽可能节约的资源进行节约。而在一个系统的数据访问中,系统的瓶颈往往是来自于数据库,因此我们要尽可能减少对数据库的访问!在不影响用户体验的情况下,对于一些静态或者变化不大的页面,我们使用缓存来减少对数据库的访问!

    1、缓存提高系统访问速度的原理是什么?

    缓存可以降低 逻辑复杂度,访问数据库次数,从未大幅减少服务器响应时间

    我们都知道在一个请求中,逻辑越复杂,调用,依赖,访问数据库的越多,耗时也就越长,响应时间也就越长,性能也就越差!因此降低逻辑复杂度,减低耦合,提高内聚,减少数据库访问,将频繁用到的变化不大的数据给缓存起来也就成为了提高性能的主要核心。

    2、使用缓存的核心通用逻辑是什么?

    当客户的请求到达后端时,先去redis中查询缓存,如果缓存中找不到,则进行数据库逻辑操作,然后渲染,存入缓存并返回给前端!如果在缓存中找到了则直接返回给前端。

    存储在Redis缓存中的页面需要设置超时时间,缓存的时间长度根据页面数据变化频繁程度适当调整!目前大多数页面缓存都是在60~120秒,少数几乎不变化的可以调整到5分钟!

    3、页面缓存的时间如何设置?

    缓存的时间长度根据页面数据变化频繁程度适当调整!目前大多数页面缓存都是在60~120秒,少数几乎不变化的可以调整到5分钟!

    4、热点数据是什么?

    所谓热点数据,就是指在某段时间内被频繁使用的对象数据。比如用户登录信息、点赞信息、网站人数。

    所谓热点数据,就是指在某段时间内被频繁使用的对象数据。比如用户登录信息,用户在登录后,每次访问都会携带其cookie信息进入后端,当信息到达后端后,其cookie信息就是我们存在redis中的key值。在这一步我们会做四个操作,并且在某些时候可使用拦截器进行处理:

    5、热点数据缓存思路是什么?

    频繁更新的数据:比如点赞次数,在线人数,达到一定的量后再一次性更新。
    量大的数据:数据库更新的时候同时更新缓存,每次从缓存中取。
    全局信息:比如用户名信息,设置全局缓存。

    <1>当用户操作进来的时候,我们获取到Cookie值并在Redis中查找,找到用户信息则刷新用户的登录时间并允许用户通过,找不到用户信息则拒绝用户继续往下!,在后面的数据操作中,如果存在需要使用用户信息的操作,则去Redis中查找,如果存在则允许操作!
    <2>对于热点数据源,被高频访问的不缺分权限信息的热点数据,则设置全局缓存,定时更新则缓存数据,当有操作到此类的热点数据缓存则主动更新缓存中的信息,将用户拦截在数据之外!
    <3>当涉及到用户登录的热点数据被更新后,需要根据用户的token作为key值重新写入或者强制用户重新登录!
    <4>对于需要频繁更新的数据或写入数据的数据,比如点赞次数,在线人数,可以设置一个层级,在没有达到层级前写在缓存中,每次只更新缓存则可以,当到一定次数则写入数据库!

    6、缓存雪崩是什么?

    缓存雪崩是指因为数据未加载到缓存中,或者缓存同一时间大面积的失效,在某一时刻大量的缓存没有命中,从而导致所有请求都去查数据库,导致数据库CPU和内存负载过高,甚至宕机!

    7、造成缓存雪崩的可能原因及预防?

    缓存穿透:对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃:查询一个数据库必然不存在的数据,那么缓存里面也没有。如果有人恶意破坏,发送高频请求,那么很可能直接对DB造成影响。
    缓存失效:尽量让失效时间点均匀分布:如果缓存集中在一段时间内失效,DB的压力凸显,DB负载急剧上升
    缓存预热:开发人员主动将数据加载到缓存中:系统部署时,防止用户一瞬间访问数据库,负载过大


    1. 缓存穿透:查询一个数据库必然不存在的数据,那么缓存里面也没有。比如文章表中查询一个不存在的id,每次都会访问DB,如果有人恶意破坏,发送高频请求,那么很可能直接对DB造成影响。
    解决办法:对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃。或者对于查询为空的字段,设置一个默认值在缓存中,如果查询到则返回默认值! 或者使用具备特点的key值,如果不符合则经由于系统过滤掉,不进入缓存也不进入数据库,此做法可以降低一定的压力,但是解决不了根本的问题。
    2.缓存失效:如果缓存集中在一段时间内失效,DB的压力凸显,DB负载急剧上升。这个没有完美解决办法,但可以分析用户行为,尽量让失效时间点均匀分布。
    3.缓存预热:系统部署时,防止用户一瞬间访问数据库,负载过大,由开发人员主动将数据加载到缓存中!

    8、静态资源优化方式?

    1.JS/CSS压缩,静态资源尽量使用压缩版的库和包,以减少浏览器加载和请求的流量
    2.多个js/css组合到一个请求,减少连接数(正常30个,从服务端获取,多次访问,通过http获取),把多个文件通过一个js/css一次性请求下来 配置 tengine模块实现!
    3.将多个Js/css的请求合并为一个
    4.CDN:用于解决网络拥挤:内容分发网络,将数据缓存到网络节点上,用户请求来根据位置定向访问到距离最近的节点,可用于解决网络拥挤,跟代码层面关系不是很大,在请求没到网站之前,CDN会根据客户的位置将请求分发到就近地网路节点上,如果节点有则直接返回!

    二、页面优化缓存技术+资源静态化+前后端分离?

    参考:页面优化缓存技术+资源静态化+前后端分离?
    https://blog.csdn.net/qq_36505948/article/details/82620908

    《目录》

    ---------->缓存的需要,缓存的原理

    ---------->页面缓存的思路

    ---------->热点数据缓存的思路,4个点

    ---------->页面局部缓存(与静态缓存的信息是相似的)

    ---------->缓存可能引起的问题以及解决思路

    ---------->由于后端跳转页面转向ajax技术请求参数的页面静态化技术与思路,这一步也是前后端分离的实现

    ---------->SpringBoot的设置使得静态页面缓存在浏览器,与浏览器的基本查看


    一、为什么要使用页面缓存技术?

    系统都是逐渐演进的,一个系统在运行中必须是根据场景逐渐地提高优化性能。高并发就是对资源的节约的考验,这种考验除了更换优秀和先进的技术,优化架构,还在于从小处出发,对尽可能节约的资源进行节约。而在一个系统的数据访问中,系统的瓶颈往往是来自于数据库,因此我们要尽可能减少对数据库的访问!在不影响用户体验的情况下,对于一些静态或者变化不大的页面,我们使用缓存来减少对数据库的访问!


    二、缓存技术的原理?

    我们都知道在一个请求中,逻辑越复杂,调用,依赖,访问数据库的越多,耗时也就越长,响应时间也就越长,性能也就越差!因此降低逻辑复杂度,减低耦合,提高内聚,减少数据库访问,将频繁用到的变化不大的数据给缓存起来也就成为了提高性能的主要核心。


    1.页面缓存思路:

    首先我们需要明白,一个页面是从后端提高数据后,交给springMvc或者SpringBoot进行渲染,主要的页面消耗是在渲染这部分。因此我们需要在这之前进行拦截。(针对于依靠后端进行页面跳转和渲染的缓存初始阶段)

    核心通用逻辑:当客户的请求到达后端时,先去redis中查询缓存,如果缓存中找不到,则进行数据库逻辑操作,然后渲染,存入缓存并返回给前端!如果在缓存中找到了则直接返回给前端。存储在Redis缓存中的页面需要设置超时时间,缓存的时间长度根据页面数据变化频繁程度适当调整!目前大多数页面缓存都是在60~120秒,少数几乎不变化的可以调整到5分钟!

    2.热点数据缓存思路:

    所谓热点数据,就是指在某段时间内被频繁使用的对象数据。比如用户登录信息,用户在登录后,每次访问都会携带其cookie信息进入后端,当信息到达后端后,其cookie信息就是我们存在redis中的key值。在这一步我们会做四个操作,并且在某些时候可使用拦截器进行处理:

    <1>当用户操作进来的时候,我们获取到Cookie值并在Redis中查找,找到用户信息则刷新用户的登录时间并允许用户通过,找不到用户信息则拒绝用户继续往下!,在后面的数据操作中,如果存在需要使用用户信息的操作,则去Redis中查找,如果存在则允许操作!

    <2>对于热点数据源,被高频访问的不缺分权限信息的热点数据,则设置全局缓存,定时更新则缓存数据,当有操作到此类的热点数据缓存则主动更新缓存中的信息,将用户拦截在数据之外!

    <3>当涉及到用户登录的热点数据被更新后,需要根据用户的token作为key值重新写入或者强制用户重新登录!

    <4>对于需要频繁更新的数据或写入数据的数据,比如点赞次数,在线人数,可以设置一个层级,在没有达到层级前写在缓存中,每次只更新缓存则可以,当到一定次数则写入数据库!


    2.页面局部缓存:

    热点数据缓存,页面静态化进行ajax请求信息更新,此类信息一般都是比较频繁发生变化的,涉及的可能是需要保存在数据库的操作,类似表格信息,即时刷新的数据等!如果是属于查看类的并且前端大量请求,可以经由于后端监控,定时写入缓存!

    核心通用逻辑:一般情况下封装以类名--对象名为组合的字符串作为Redis的Key值,然后存入数据库,每次访问到目标的方法都先去缓存读取,然后再处理!


    三、缓存雪崩-数据穿透问题:

    缓存雪崩:缓存雪崩是指因为数据未加载到缓存中,或者缓存同一时间大面积的失效,在某一时刻大量的缓存没有命中,从而导致所有请求都去查数据库,导致数据库CPU和内存负载过高,甚至宕机!

    1. 缓存穿透:查询一个数据库必然不存在的数据,那么缓存里面也没有。比如文章表中查询一个不存在的id,每次都会访问DB,如果有人恶意破坏,发送高频请求,那么很可能直接对DB造成影响。

    解决办法:对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃。或者对于查询为空的字段,设置一个默认值在缓存中,如果查询到则返回默认值! 或者使用具备特点的key值,如果不符合则经由于系统过滤掉,不进入缓存也不进入数据库,此做法可以降低一定的压力,但是解决不了根本的问题。

    2.缓存失效:如果缓存集中在一段时间内失效,DB的压力凸显,DB负载急剧上升。这个没有完美解决办法,但可以分析用户行为,尽量让失效时间点均匀分布。

    3.缓存预热:系统部署时,防止用户一瞬间访问数据库,负载过大,由开发人员主动将数据加载到缓存中!

    单机---系统:手动刷新页面既可以了,或者定时缓存缓存

    分布式系统: 分布式系统问题在于数据量非常大,缓存可能会导致数据库宕机!通过程序进行单个缓存加载!


    四、Redis页面缓存实现

    1.请求到来后,先调用根据key值去redis访问,找到则返回

    2.SpringBoot的redis中找不到调用webConext()对象进行加载

    1. 将Thyemleaf的thymeleafViewResolver给注入到Controller中
    2. 进行页面渲染:
     WebContext  ctx=new 
     WebContext(request,response,request.getServletContext(),request.getLocale(),model.asMap());
            html=thymeleafViewResolver.getTemplateEngine().process("页面名称无后缀",ctx);
    3. 返回页面信息
    ================================================================================================
    方法的返回以String对象,并且页面不可以使用ResController作为注解(以json返回),页面的reqestMapper里
    设置:
     @RequestMapping(value = "/xxxx",produces ="text/html")//可能没有数据
     @ResponseBody
    
    
    

    3.SpringMvc的redis中使用拦截器或者过滤器用ModelAndView渲染,拦截器的用法过于简单,自行百度,不做解释


    五、页面静态化?
    除了将页面资源与数据进行缓存以减少数据库访问外,还可以利用浏览器特点,将页面给完全缓存在浏览器中,等到浏览器过时,再访问项目,项目的请求经过项目内部缓存,缓存如果过时,再访问数据库!

    将页面静态化的特点必须解决页面如何获取与处理数据,如何跳转页面的问题!在此我们可以参考 ajax技术 ,将请求与页面完全独立,保证页面是静态页面,而请求通过Ajax技术局部刷新与全局刷新的特点来实现!变化如下:

    1----原流程?

    2----静态化页面流程?

    注意:此流程为页面静态化的流程,前端的页面跳转将由页面之间直接完成,不在通过后端!页面之间的数据加载,则是通过Ajax请求的形式,请求后端返回JSON数据流。在请求中有缓存则显访问缓存,没有缓存或者缓存超时则直接访问下一层,知道完整返回数据!


    3------浏览器设置与分析?
    一般情况下,一个正常的请求都具备了请求报文和响应报文,请求和响应均分成三个部分,请求头则维护了请求协议类型,而请求和响应报文则维护了对于报文体的参数,生命,来源等信息!第三部分则是本次请求的内容,也就是我们说的报文体!对于浏览器来说,他更像是一个负责页面渲染和参数设定的容器,读取报文头的信息对报问题进行相关的操作,并通过一定的通过规则展示给使用者!


    浏览器的主要功能是将用户选择的web资源呈现出来,它需要从服务器请求资源,并将其显示在浏览器窗口中,资源的格式通常是HTML,也包括PDF、image及其他格式。 HTML和CSS规范中规定了浏览器解释html文档的方式,由W3C组织对这些规范进行维护,W3C是负责制定web标准的组织。

    关于浏览器原理可以参考:https://kb.cnblogs.com/page/129756/

    页面静态化的一个特点也是可以将静态页面给缓存在用户浏览器一端。同一个页面,在页面的生命周期没到之前,用户的请求都是在本地进行(304);

    用于识别是否缓存并且区分缓存时间的主要是以下三个模块:

    Pragma:支持http1.0版本的缓存
    Expire:http2.0可以用,也向下兼容http1.0版本,16进制的字符串,以格里尼治时间也准,以服务端时间来定义缓存你是否超时,但由于客户端与服务端缓存时间经常不一致,所以容易造成缓存失效!
    Cache-control:Http版本1.0-2.0都可以用,以秒为单位,并且可以指定缓存为多少秒,对缓存时间进行倒计时,同时不会根据客户端时间来衡量,也不会根据服务端时间衡量,完全依赖信息本身!

    cache-control=max-age=3600:服务端告诉浏览器指定3600秒
    观察:在网络XHR上面的连接输出字段可以看到连接已经缓存,在缓存有效期内,每一次请求都是返回304,但只是浏览器自己处理,实际请求并没有到达后端系统!

    在springBoot后端的application.yml做如下设置:

    resources:
        add-mappings: true  #配置
        chain:
          cache: true
          enabled: true
          gzipped: true#是否执行压缩
          html-application-cache: true  #是否启动html引用的缓存
        static-locations: classpath:/static/    #静态资源页面的位置
        cache-period: 3600  #页面浏览器的配置缓存多少秒
    ============================================================================================
    将该信息放置于spring的节点下

    4-----静态资源优化?

    除了对静态页面优化,我们还可以通过一些方式减少流量,提供访问的速度!当用户的请求越小,性能也就相对越好!
    1.JS/CSS压缩,静态资源尽量使用压缩版的库和包,以减少浏览器加载和请求的流量
    2. 多个js/css组合到一个请求,减少连接数(正常30个,从服务端获取,多次访问,通过http获取),把多个文件通过一个js/css一次性请求下来 配置 tengine模块实现!

    3.将多个Js/css的请求合并为一个
    4.CDN:内容分发网络,将数据缓存到网络节点上,用户请求来根据位置定向访问到距离最近的节点,可用于解决网络拥挤,跟代码层面关系不是很大,在请求没到网站之前,CDN会根据客户的位置将请求分发到就近地网路节点上,如果节点有则直接返回!

    注意:tengine与nginx的功能基本是一样的,继承了nginx所有特性,并且拥有可以对静态资源压缩合并请求等功能,详情可参考tengine.taobaoorg ,可以参照Nginx的方式来配置Tengine!


    六--------对于缓存?

    对于一个项目来说,其瓶颈往往是在于数据库的瓶颈。除了业务代码的稳定性,我们所做的操作目的都是在减少数据库的压力。通过Redis页面缓存,通过浏览器缓存,通过页面静态化,通过Redis页面静态缓存,通过Redis热点数据缓存,Nginx缓存,Tengine缓存,CDN缓存等,层层拦截,以减少对数据库的访问!

    但是对于数据来说,一切的缓存都是建立在不影响客户体验的基础上,缓存因为其特点,仍热存在着数据不同步的问题!

    针对这个问题,能处理的只有?
    定时刷新缓存,存储变化非常小的页面信息!

    主动监控更新缓存!

     
  • 相关阅读:
    flexbox弹性盒子布局
    LAMP环境 源码包安装
    用条件注释判断浏览器版本,解决兼容问题
    事件冒泡和事件捕获
    为js和css文件自动添加版本号
    uEditor独立图片上传
    修改netbeans模版头部的说明
    thinkphp多表关联并且分页
    thinkphp 独立分组配置
    荣耀路由HiLink一键组网如何实现?
  • 原文地址:https://www.cnblogs.com/Renyi-Fan/p/10907658.html
Copyright © 2011-2022 走看看