https://blog.csdn.net/baidu_33497625/article/details/50801571

一、什么是缓存

1、Cache是高速缓冲存储器 一种特殊的存储器子系统,其中复制了频繁使用的数据以利于快速访问
2、凡是位于速度相差较大的两种硬件/软件之间的,用于协调两者数据传输速度差异的结构,均可称之为 Cache

二、缓存的分类

1、基于web应用的系统架构图

2、在系统架构的不同层级之间,为了加快访问速度,都可以存在缓存

  • 操作系统磁盘缓存->减少磁盘机械操作
  • 数据库缓存->减少文件系统I/O
  • 应用程序缓存->减少对数据库的查询 
  • Web服务器缓存->减少应用服务器请求
  • 客户端浏览器缓存->减少对网站的访问

三、操作系统缓存

1、文件系统提供的Disk Cache:操作系统会把经常访问到的文件内容放入到内存当中,由文件系统来管理
2、当应用程序通过文件系统访问磁盘文件的时候,操作系统从Disk Cache当中读取文件内容,加速了文件读取速度
3、Disk Cache由操作系统来自动管理,一般不用人工干预,但应当保证物理内存充足,以便于操作系统可以使用尽量多的内存充当Disk Cache,加速文件读取速度
4、特殊的应用程序对文件系统Disk Cache有很高的要求,会绕开文件系统Disk Cache,直接访问磁盘分区,自己实现Disk 
5、Cache策略

  • Oracle的raw device(裸设备) – 直接抛弃文件系统
  • MySQL的InnoDB: innodb_flush_method = O_DIRECT

3.1 高速缓存cache

cache位于cpu和主存储器间的高速小容量存储器,由静态存储信片SRAM组成,接近cpu的速度。cache可以大幅度提升cpu内部读取数据的命中率,从而提高系统的性能。

通过由以下方面组成:

联想存储器:根据内容进行寻址的存储器,只存在部分信息,根据内容进行检索;

地址转换部件:通过联想模块简历的目录表以实现快速地址转换。命中直接访问cache。未命中从内存读取放入cache。

替换部件:在缓存已满时,按一定策略进行数据块替换(先进先出FIFO、最近最少用LRU、随机替换、最不常用LFU),并修改地址转换部件。

1)cache一致性问题

  • 对cache进行更新时,存在cache与主存如何保持一致的问题;
  • 多个设备访问主存,IO可直接读写内存,如果cache内容被修改,则IO设备读出对应主存单元的内容无效。弱IO修改了主存单元,则cache无效;
  • 多个cpu带各自的cache而共享主存,某个cpu修改了自身的cache,则对应的主存单元和其他的cpu中对应的内容都变为无效。

2)解决方法

关键在于处理好写操作

全写法write Through(通写法、写直达法、直写法):若写命中九同时写cache和主存;若写不命中,1)写分配:先写主存块中更新相应的存储空间,然后再分配cache行,更新主存块九装入cache行,利用空间的局部性,每次不命中都要从主存读一个块;2)非全写分配:直接写主存单元,不把主内存快装入cache。

回写法write back一次性写方式、写回法:只写cache不写主存,但是控制复杂。


四、数据库缓存


1、重要性

  • 数据库通常是企业应用系统最核心的部分
  • 数据库保存的数据量通常非常庞大
  • 数据库查询操作通常很频繁,有时还很复杂
  • 以上原因造成数据库查询会引起非常频繁的磁盘I/O读取操作,迫使CPU挂起等待,数据库性能极度低下

2、缓存策略
     a、Query Cache

    • 以SQL作为key值缓存查询结果集
    • 一旦查询涉及的表记录被修改,缓存就会被自动删除
    • 设置合适的Query Cache会极大提高数据库性能
    • Query Cache并非越大越好,过大的Qquery Cache会浪费内存。
    • MySQL: query_cache_size= 128M

     b、Data Buffer

    • data buffer是数据库数据在内存中的容器
    • data buffer的命中率直接决定了数据库的性能
    • data buffer越大越好,多多益善
    • MySQL的InnoDB buffer:innodb_buffer_pool_size = 2G
    • MySQL建议buffer pool开大到服务器物理内存60-80%

4.1 数据库缓存的三种方式

1)cache Aside更新模式:同时更新缓存和数据库;

失效:应用程序从cache取数据,没取到,则从数据库读取,成果之后放到缓存;

命中:应用程序从cache取数据,取到返回;

更新:把数据放到数据库,成功后,让缓存失效;

为什么先更新数据库,后让缓存失效?

1、先更新数据库,后更新缓存:两个并发写操作回导致脏数据;

2、先删除缓存,再更新数据库:逻辑错误,两个并发读和写操作导致脏数据;

3、先更新数据库,再删除缓存;推荐使用,极端情况(查询缓存不命中,进行数据库查询,并发出现更新操作,更新了数据库,删除了缓存,然而读操作从数据库读取老数据回了缓存,造成数据不一致,这种极少发生。)

2)Read/Write through 更新模式:先更新缓存,缓存负责同步更新数据库;

只需要维护缓存

Read through :查询操作中更新缓存;

Write through :更新数据的时候,更新缓存;

3)Write behind caching 更新模式:先更新缓存,缓存定时异步更新数据库;

好处:直接操作内存,速度快,可以合并对同一数据的多次操作到数据库,所以性能得到很大的提高;

问题:数据不是强一致,可能回丢失(系统断电等);缓存失效才实现真正的持久性存储;

五、应用程序缓存


1、对象缓存

  • 由O/R Mapping框架例如Hibernate提供,透明性访问,细颗粒度缓存数据库查询结果,无需业务代码显式编程,是最省事的缓存策略
  • 当软件结构按照O/R Mapping框架的要求进行针对性设计,使用对象缓存将会极大降低Web系统对于数据库的访问请求
  • 良好的设计数据库结构和利用对象缓存,能够提供极高的性能,对象缓存适合OLTP(联机事务处理)应用

2、查询缓存

  • 对数据库查询结果集进行缓存,类似数据库的Query Cache
  • 适用于一些耗时,但是时效性要求比较低的场景。查询缓存和对象缓存适用的场景不一样,是互为补充的
  • 当查询结果集涉及的表记录被修改以后,需要注意清理缓存

3、页面缓存
     a、作用

    • 针对页面的缓存技术不但可以减轻数据库服务器压力,还可以减轻应用服务器压力
    • 好的页面缓存可以极大提高页面渲染速度
    • 页面缓存的难点在于如何清理过期的缓存

    b、分类
         I、动态页面静态化

    • 利用模板技术将访问过一次的动态页面生成静态html,同时修改页面链接,下一次请求直接访问静态链接页面
    • 动态页面静态化技术的广泛应用于互联网CMS/新闻类Web应用,但也有BBS应用使用该技术,例如Discuz!
    • 无法进行权限验证,无法显示个性化信息
    • 可以使用AJAX请求弥补动态页面静态化的某些缺点

        II、Servlet缓存

    • 针对URL访问返回的页面结果进行缓存,适用于粗粒度的页面缓存,例如新闻发布
    • 可以进行权限的检查
    • OScache提供了简单的Servlet缓存(通过web.xml中的配置)
    • 也可以自己编程实现Servlet缓存

        III、页面内部缓存

    • 针对动态页面的局部片断内容进行缓存,适用于一些个性化但不经常更新的页面(例如博客)
    • OSCache提供了简单的页面缓存
    • 可以自行扩展JSP Tag实现页面局部缓存


六、web服务器端缓存

 

  • 基于代理服务器模式的Web服务器端缓存,如squid/nginx
  • Web服务器缓存技术被用来实现CDN(内容分发网络 content delivery network)
  • 被国内主流门户网站大量采用
  • 不需要编程,但仅限于新闻发布类网站,页面实时性要求不高

七、基于ajax的浏览器缓存

 

  • 使用AJAX调用的时候,将数据库在浏览器端缓存
  • 只要不离开当前页面,不刷新当前页面,就可以直接读取缓存数据
  • 只适用于使用AJAX技术的页面

一、cookie机制和session机制的区别

具体来说cookie机制采用的是在客户端保持状态的方案,而session机制采用的是在服务器端保持状态的方案。

同时我们也看到,由于才服务器端保持状态的方案在客户端也需要保存一个标识,所以session

机制可能需要借助于cookie机制来达到保存标识的目的,但实际上还有其他选择

二、会话cookie和持久cookie的区别

如果不设置过期时间,则表示这个cookie生命周期为浏览器会话期间,只要关闭浏览器窗口,cookie就消失了。这种生命期为浏览会话期的cookie被称为会话cookie。会话cookie一般不保存在硬盘上而是保存在内存里。

如果设置了过期时间,浏览器就会把cookie保存到硬盘上,关闭后再次打开浏览器,这些cookie依然有效直到超过设定的过期时间。

存储在硬盘上的cookie可以在不同的浏览器进程间共享,比如两个IE窗口。而对于保存在内存的cookie,不同的浏览器有不同的处理方式。

三、如何利用实现自动登录

当用户在某个网站注册后,就会收到一个惟一用户ID的cookie。客户后来重新连接时,这个

用户ID会自动返回,服务器对它进行检查,确定它是否为注册用户且选择了自动登录,从而使用户务需给出明确的用户名和密码,就可以访问服务器上的资源。

四、如何根据用户的爱好定制站点

网站可以使用cookie记录用户的意愿。对于简单的设置,网站可以直接将页面的设置存储在cookie中完成定制。然而对于更复杂的定制,网站只需仅将一个惟一的标识符发送给用户,由服务器端的数据库存储每个标识符对应的页面设置。

五、cookie的发送

1.创建Cookie对象

2.设置最大时效

3.将Cookie放入到HTTP响应报头

如果你创建了一个cookie,并将他发送到浏览器,默认情况下它是一个会话级别的cookie:存储在浏览器的内存中,用户退出浏览器之后被删除。如果你希望浏览器将该cookie存储在磁盘上,则

需要使用maxAge,并给出一个以秒为单位的时间。将最大时效设为0则是命令浏览器删除该cookie。

发送cookie需要使用HttpServletResponse的addCookie方法,将cookie插入到一个Set-CookieHTTP请求报头中。由于这个方法并不修改任何之前指定的Set-Cookie报头,而是创建新的报头,因此我们将这个方法称为是addCookie,而非setCookie。同样要记住响应报头必须在任何文档内容发送到客户端之前设置。

六、cookie的读取

1.调用request.getCookie

要获取有浏览器发送来的cookie,需要调用HttpServletRequest的getCookies方法,这个调用返回Cookie对象的数组,对应由HTTP请求中Cookie报头输入的值。

2.对数组进行循环,调用每个cookie的getName方法,直到找到感兴趣的cookie为止

cookie与你的主机(域)相关,而非你的servlet或JSP页面。因而,尽管你的servlet可能只发送了单个cookie,你也可能会得到许多不相关的cookie。

例如:

StringcookieName=“userID”;

Cookiecookies[]=request.getCookies();

if(cookies!=null){

for(inti=0;i

Cookiecookie=cookies[i];

if(cookieName.equals(cookie.getName())){

doSomethingWith(cookie.getValue());}}}

七、如何使用cookie检测初访者

A.调用HttpServletRequest.getCookies()获取Cookie数组

B.在循环中检索指定名字的cookie是否存在以及对应的值是否正确

C.如果是则退出循环并设置区别标识

D.根据区别标识判断用户是否为初访者从而进行不同的操作

八、使用cookie检测初访者的常见错误

不能仅仅因为cookie数组中不存在在特定的数据项就认为用户是个初访者。如果cookie数组为null,客户可能是一个初访者,也可能是由于用户将cookie删除或禁用造成的结果。

但是,如果数组非null,也不过是显示客户曾经到过你的网站或域,并不能说明他们曾经访问过你的servlet。其它servlet、JSP页面以及非JavaWeb应用都可以设置cookie,依据路径的设置,其中的任何cookie都有可能返回给用户的浏览器。

正确的做法是判断cookie数组是否为空且是否存在指定的Cookie对象且值正确。

Logo

开源、云原生的融合云平台

更多推荐