/**
* 作者:ahuaxuan
* 日期:2009-03-08
*/
看一粒沙中的世界, 一朵野花中的天堂。 把无限握于掌中, 把永恒握于瞬间。——威廉• 布莱克
开始讨论缓存之前,让我们先来讨论讨论另外一个问题:理论和实践.从ahuaxuan接触的程序员来看,有的程序员偏实践,有的程序员偏理论,但是这都是不好的行为,理论和实践同样重要,我们在做很多核心的算法的时候,没有理论根本无从下手,而在我们多年的实践中,不总结理论就不能加深自己的理解.所以理论和实践同等重要.
缓存是当今各种软件或者硬件系统中不可缺少的技术之一,所以对每个程序员来说都显得异常重要,对ahuaxuan来说亦是如此.如果说用dfa实现文字过滤是从理论到实践,那么本文便是从实践中总结出得理论.
在讨论缓存功能之前,我们首先来了解一下缓存这个东西本身.ahuaxuan根据自己的经验把缓存问题细分为4类小问题.
1缓存为什么要存在?
2缓存可以存在于什么地方?
3缓存有哪些属性?
4缓存介质?
搞清楚这4个问题,那么我们就可以随意的通过应用的场景来判断使用何种缓存了.
下面ahuaxuan和大家一一分析这4个问题.
1. 缓存为什么要存在?
一般情况下,一个网站,或者一个应用,它的一般形式是,浏览器请求应用服务器,应用服务器做一堆计算后再请求数据库,数据库收到请求后再作一堆计算后把数据返回给应用服务器,应用服务器再作一堆计算后把数据返回给浏览器.这个是一个标准流程.但是随着互连网的普及,上网的人越来越多,网上的信息量也越来越多,在这两个越来越多的情况下,我们的应用需要支撑的并发量就越来越多.然后我们的应用服务器和数据库服务器所做的计算也越来越多,但是往往我们的应用服务器资源是有限的,数据库每秒中接受请求的次数也是有限的(谁叫俺们的硬盘转速有限呢).如果利用有限的资源来提供尽可能大的吞吐量呢,一个办法:减少计算量,缩短请求流程(减少网络io或者硬盘io),这时候缓存就可以大展手脚了.缓存的基本原理就是打破上图中所描绘的标准流程,在这个标准流程中,任何一个环节都可以被切断.请求可以从缓存里取到数据直接返回.这样不但节省了时间,提高了响应速度,而且也节省了硬件资源.可以让我们有限的硬件资源来服务更多的用户.
2 缓存可以存在于什么地方?
浏览器---浏览器和app之间---分过层的app-数据库
在上图中,我们可以看到一次请求的一般流程,下面我们重新绘制这张图,让我们的结构稍微复杂一点点.
(将app分层)
浏览器---浏览器和app之间---分过层的app-数据库
理论上来将,请求的任何一个环节都是缓存可以作用的地方.第一个环节,浏览器,如果数据存在浏览器上,那么对用户来说速度是最快的,因为这个时候根本无需网络请求.第二个环节,浏览器和app之间,如果缓存加在这个地方,那么缓存对app来说是透明的.而且这个缓存中存放的是完整的页面.第三个节点,app中本身就有几个层次,那么缓存也可以放在不同的层次上,这一部分是情况或者场景比较复杂的部分.选择缓存时需要谨慎.第四个环节,数据库中也可以有缓存,比如说mysql的querycache.
那么也就是说在整个请求流程的任何一点,我们都可以加缓存.但是是所有的数据都可以放进缓存的吗.当然不是,需要放进缓存的数据总是有一些特征的,要清楚的判断数据是否可以被缓存,可以被怎样缓存就必须要从数据的变化特征下手.
数据有哪些变化特征?最简单的就是两种,变和不变.我们都知道,不会变化的数据不需要每次都进行计算.问题是难道所有的数据理论上来讲都会变化,变化是世界永恒的主题.也就是说我们把数据分为变和不变两种是不对的,那么就让我们再加一个条件:时间.那么我们就可以把数据特征总结为一段时间内变或者不变.那么根据这个数据特征,我们就可以在合适的位置和合适的缓存类型中缓存该数据.
3缓存有哪些属性
从面向对象的角度来看,缓存就是一个对象,那么是对象,必然有属性.那么下面我们来探讨一下缓存有哪些属性.以下列举我们常用到的3个属性.
(1) 命中率
命中率是指请求缓存次数和缓存返回正确结果次数的比例.比例越高,就证明缓存的使用率越高.
命中率问题是缓存中的一个非常重要的问题,我们都希望自己缓存的命中率能达到100%,但是往往事与愿违,而且缓存命中率是衡量缓存有效性的重要指标.
(2) 最大元素
缓存中可以存放得最大元素得数量,一旦缓存中元素数量超过这个值,那么将会起用缓存清空策略,根据不同的场景合理的设置最大元素值往往可以一定程度上提高缓存的命中率.从而更有效的时候缓存.
(3) 清空策略
1 FIFO ,first in first out ,最先进入缓存得数据在缓存空间不够情况下(超出最大元素限制时)会被首先清理出去
2 LFU , Less Frequently Used ,一直以来最少被使用的元素会被被清理掉。这就要求缓存的元素有一个hit 属性,在缓存空间不够得情况下,hit 值最小的将会被清出缓存。
2 LRU ,Least Recently Used ,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。
4缓存介质
从硬件介质上来将无非就是两种,内存和硬盘(对应应用层的程序来讲不用考虑寄存器等问题).但是往往我们不会从硬件上来划分,一般的划分方法是从技术上划分,可以分成几种,内存,硬盘文件.数据库.
(1) 内存.将缓存放在内存中是最快的选择,任何程序直接操作内存都比操作硬盘要快的多,但是如果你的数据要考虑到break down的问题,因为放在内存中的数据我们称之为没有持久话的数据,如果硬盘上没有备份,机器down机之后,很难或者无法恢复.
(2) 硬盘.一般来说,很多缓存框架会结合使用内存和硬盘,比如给内存分配的空间有满了之后,会让用户选择把需要退出内存空间的数据持久化到硬盘.当然也选择直接把数据放一份到硬盘(内存中一份,硬盘中一份,down机也不怕).也有其他的缓存是直接把数据放到硬盘上.
(3) 数据库.说到数据库,可能有的人会想,之前不是讲到要减少数据库查询的次数,减少数据库计算的压力吗,现在怎么又用数据库作为缓存的介质了呢.这是因为数据库又很多种类型,比如berkleydb,这种db不支持sql语句,没有sql引擎,只是key和value的存储结构,所以速度非常的快,在当代一般的pc上,每秒中十几w次查询都是没有问题的(当然这个是根据业务特征来决定的,如果您访问的数据在分布上是均匀的,那ahuaxuan可不能保证这个速度了).
除了缓存介质之外,ahuaxuan根据缓存和应用的耦合程度将其划分为local cache和remote cache.
Local cache是指包含在应用之中的缓存组件.而remote cache指和应用解耦在应用之外的缓存组件.典型的local cache有ehcache,oscache,而remote cache有大名鼎鼎的memcached.
Localcache最大的优点是应用和cache的时候是在同一个进程内部,请求缓存非常快速,完全不需要网络开销等.所以单应用,不需要集群或者集群情况下cache node不需要相互通知的情况下使用local cache比较合适.这也是java中ehcache和oscache这么流行的原因.
但是Local cache是有一定的缺点的,一般这种缓存框架(比如java中的ehcache或者oscache)都是local cache.也就是跟着应用程序走的,多个应用程序无法直接共享缓存,应用集群的情况下这个问题更加明显,当然也有的缓存组件提供了集群节点相互通知缓存更新的功能,但是由于这个是广播,或者是环路更新,在缓存更新频繁的情况下会导致网络io开销非常大,严重的时候会影响应用的正常运行.而且如果缓存中数据量较大得情况下使用localcache意味着每个应用都有一份这么大得缓存,着绝对是对内存的浪费.
所以这个情况下,往往我们会选择remote cache,比如memcached.这样集群或者分布式的情况下各个应用都可以共享memcached中的数据,这些应用都通过socket和基于tcp/ip协议上层的memcached协议直接连接到memcached,有一个app更新了memcached中的值,所有的应用都能拿到最新的值.虽然这个时候多了很多了网络上的开销,但是往往这种方案要比localcache广播或环路更新cache节点要普遍的多,而且性能也比后者高.由于数据只需要保存一份,所以也提高了内存的使用率.
通过以上分析可以看出,不管是local cache,还是remote cache在缓存领域都有自己的一席之地,所以ahuaxuan建议在选择或者使用缓存时一定要根据缓存的特征和我们的业务场景准确判断使用何种缓存.这样才能充分发挥缓存的功能.
Ahuaxuan认为,缓存的使用是架构师的必备技能,好的架构师能够根据数据的类型,业务的场景来准确的判断出使用何种类型的缓存,并且如何使用这种类型的缓存.在缓存的世界里也没有银弹,目前还没有一种缓存可以解决任何的业务场景或者数据类型,如果这种技术出现了,那架构师就又更不值钱了.呵呵.
本文是ahuaxuan从自己的实践中总结出来的一些小小的心得,未参考任何文章,,所以可能未必好,未必全面,未必令您满意,欢迎拍砖.
最后说一说写这篇文章的初衷,周末有人让我说说我对缓存的理解,我的回答的是对缓存的理解无法用一句话来表述,起码写5篇文章.那本文只是第一篇. 待续-------------
- 大小: 10.1 KB
分享到:
- 2009-03-09 10:52
- 浏览 2226
- 评论(7)
- 论坛回复 / 浏览 (7 / 7250)
- 查看更多
相关推荐
基于2.2Fsp1所以补丁就不用说了<br> 希望各位朋友在使用过程中做好我们社区的友情链接,尊重别人劳动成功~谢谢<br> <br> 增加权限查看<br> 无用数据清理<br> 注册等10秒看许可协议时间修改为0<br> 子论坛显示新方式...
5. **媒体元素**:内置的<audio>和<video>标签简化了音频和视频的嵌入,无需第三方插件。 JavaScript,作为Web开发的核心语言,与HTML5相结合,能够实现更复杂的交互逻辑和实时更新。以下是一些JavaScript在Android...
在描述地球生命的网站中,可能会使用`<h1>`至`<h6>`来定义标题,`<p>`用于段落,`<img>`用于插入图片,以及`<a>`来创建链接,引导用户了解更多地球科学的相关资源。 【网站结构与布局】 一个教育网站通常会包含多...
"my-website"通常代表用户自定义的网站名称,而“练习 01”表明这是系列练习中的第一个步骤,暗示后续可能有更复杂的任务和学习阶段。 【描述】"我的网站 我正在写自述文件" 说明了项目的核心内容,即创建一个个人...
循环缓存仅需一个指定大小的二维缓冲区,其中第一维代表缓存队列的长度(记为B),第二维代表每次采集数据的采样点数(记为S)。通过这种方式,可以实现采集线程和处理线程之间的高效协作: - **采集线程先行**:...
采用该机制明显降低了TLB的缺失代价,当第一级TLB缺失时访问第二级TLB的平均访问延时接近1个时钟周期,约为原有平均访问延时的20%,增加的面积开销仅为原内存管理单元的181%左右,具有低成本、低功耗的特征。
这个毕业设计项目——"Android应用源码之图片异步缓存两层缓存",旨在教你如何优化图片加载,提高用户体验,减少内存消耗,并且降低服务器压力。以下是这个项目中涉及的关键知识点: 1. **图片异步加载**:在...
2. **内存缓存**:内存缓存是一种快速但容量有限的存储方式。Android中,可以利用`LruCache`类来实现。该源码可能会根据内存大小动态调整缓存容量,并通过哈希表快速查找图片,提高加载速度。 3. **本地文件缓存**...
HTML 通过一系列的标签来描述文档结构,如`<div>`、`<p>`、`<a>`等,这些标签帮助开发者组织内容,创建可读性强的网页。 - **CSS** (Cascading Style Sheets):层叠样式表,主要用于描述 HTML 或 XML 文档的呈现...
《Google大数据三篇著名论文1》中的第一篇是关于Google文件系统(Google File System, GFS)的,由Sanjay Ghemawat, Howard Gobioff和Shun-Tak Leung共同撰写。该系统是为大型分布式数据密集型应用而设计的,目标是...
1. **图片加载库**:在Android应用中,我们通常会使用第三方库如Picasso、Glide或Fresco来处理图片的加载。这些库可以简化图片的网络请求、内存管理、缓存策略以及在UI线程中显示图片的工作。 2. **内存缓存**:当...
这个毕业设计的Demo主要展示了如何在Android端实现这一功能,并结合内存缓存、文件缓存以及图片淡入淡出动画,提供了一个完整的解决方案。 首先,让我们深入了解一下异步加载图片的概念。在Android应用中,如果直接...
C++11引入了标准库中的`<thread>`,提供了一种更加便捷的多线程编程方式。 5. **消息编码与解码**: 数据在网络上传输前需要进行编码,如JSON或XML格式,便于解析和存储。C++的第三方库如nlohmann/json可以帮助...
在信息技术领域,内存对象缓存系统是一种优化数据存取速度,提高系统性能的重要技术。预取策略是内存对象缓存系统中的一个关键组成部分,它的目的是预测接下来可能会被访问的数据,并提前将这些数据加载到缓存中,以...
标题“毕业设计论文-网上超市论文.rar”表明这是一个与毕业设计相关的压缩文件,主题是关于构建一个网上超市的系统。毕业设计通常是高等教育阶段学生在完成学业前的最后一项大型项目,旨在综合运用所学知识,包括...
1.逻辑设计:数据库设计的第一步是逻辑设计,逻辑设计的目的是定义数据库的逻辑结构和关系。 2.物理设计:逻辑设计完成后,需要进行物理设计,物理设计的目的是定义数据库的物理结构和存储方式。 3.数据库对象设计:...