在整个计算机体系构造中(不管是硬件层面仍是软件层面),缓存都是无处不在的。mysql
在计算机硬件构造中,因为两种介质的速度不匹配,高速介质在和低速介质交互时速度趋向低速方,这就致使了高速介质的资源闲置。而经过引入第三种介质(速度和成本介于二者中间),将低速方读写的部份内容数据保存在该介质中,高速方大多数状况下则无需和低速方直接交互,这样就能总体提高了交互的性能。这就是计算机体系中缓存的由来。比较典型的就是CPU缓存(CPU寄存器=>L1 cahce =>L2 cache =>内存=>硬盘),如图:算法
在计算机系统和应用软件层面,缓存更是无处不在。咱们在使用浏览器上网时,不少静态资源会被缓存到本地。咱们在手机上采用微信聊天时,不少好友的头像等数据会被缓存到手机中。在操做系统层面,I/O操做也会被内核缓存(通常将数据缓存在文件系统的缓存页中),固然,这个可能相比前两个场景更加抽象,但缓存的目的都是一致的,为了提高读写性能。sql
缓存在狭义上解决介质读写速度不匹配问题,广义上包括任何利用中间媒介提升速度的方法,包括:空间换时间,动态操做变为静态操做。数据库
缓存(CACHE)和缓冲(BUFFER)编程
缓存:能够共享,多种数据,大小不固定,能够重复使用,已知数据,用于提升IO效率。浏览器
缓冲:不能够共享,单一数据,大小固定,读取后失效,命中100%,未知数据,用于减小IO次数。缓存
缓存的属性服务器
命中率:从缓存中返回正确数据的次数/总请求次数。微信
容量:超过这个值启用必定的策略:转移到磁盘;转移到远端;清空部分。session
存储介质:内存、磁盘。
成本:开发成本、部署成本、硬件成本。
效率:SET效率、GET效率、序列化、哈希算法、分布式算法。
缓存的限制
因为价格的因素,缓存实现依赖的存储每每有大小限制——保存什么,舍弃什么,命中率。
缓存每每是从无到有的——在最初阶段不能发挥做用,在不命中的时候性能颠簸。
按照存储介质来分 :
内存(网站进程内、同服务器独立进程、独立服务器、分布式服务器组)。
磁盘(本地文件和数据库,独立服务器、分布式服务器组)。
缓存可使用磁盘而不只仅是内存。
按照存储的数据来分 :
直接用于输出的整页(HTML、脚本样式、图片)。
片断页(可供多个客户端使用的HTML、脚本样式等)。
索引和聚合数据(空间换时间)。
耗时查询的结果数据。
和业务相关的大块数据(列表数据,引用数据)。
和业务相关的小级数据(行级数据,资源数据)。
和上下文(用户)相关的数据(活动数据)。
按照实现方式来分 :
框架或引擎内置的缓存(好比ORM缓存和SQL SERVER缓存)。
安装特定的组件根据规则自动实现缓存(好比反向代理和输出缓存)。
须要由开发以编程方式实现的缓存(好比业务数据缓存)。
按照做用来分 :
用于数据的读取(以后介绍的大部份内容都是基于此类缓存)
用于(容许丢失)数据的写入——写到缓存的队列中,再由工做线程提交处理(写入存储)
浏览器缓存(HTTP缓存头)
代理缓存(Squid Vanish CDN)
Web服务器缓存(内核缓存、应用缓存)
页面输出缓存(片断缓存、整页缓存)
业务数据缓存(本地缓存,分布式缓存)
其它缓存(ORM、数据库、搜索引擎等缓存)
这里每一块涉及的技术和内容都比较多,暂时不展开。
缓存的常见模式:
缓存的策略:
被动更新
在获取数据的时候,若是缓存中没有(可能缓存已通过期了),则尝试去数据库中获取,最后将最新的数据再写入到缓存中。
主动更新
更新数据的时候,主动更新缓存(直接将数据写入到缓存中)。
定时更新
经过独立的线程或者任务调度,定时将缓存数据进行更新。
通知更新
能够经过MQ等方式来通知缓存更新,这其实也是一种主动更新的策略,必定程度能够解耦。
不更新
对于有些不可能发生改变的数据,能够永久缓存起来。
缓存的过时(失效)策略:
绝对的过时时间
这种是最多见的方式。当到达指定时间后,缓存将自动失效。
平滑过时
相似session的超时机制,实际使用较少。
依赖方式
在.NET平台内置的本地缓存中,支持依赖数据库或文件来更新缓存,但实际开发中不多用。
永远不过时
对于有些不可能发生改变的数据,能够永久缓存起来。
缓存的清除(替换)策略:
RAND 删除随机数据,不能反映局部性。
SIZE 删除最大的数据。
FIFO,First In First Out 删除最早进入缓存的数据,不能反映局部性。
LFU,Least Frequently Used 删除一直以来最少被使用的数据。
LRU,Least Recently Used 删除最近最少使用的数据。
其中,LUR算法是最被普遍使用的。
常见模式:
延迟加载方式:A+F
预加载方式:B/C/E+I
下一篇跟你们聊聊缓存命中率、缓存的常见问题和应对方式...