文档章节

缓存技术

丈量大地
 丈量大地
发布于 2014/05/09 10:27
字数 4542
阅读 361
收藏 38

开始讨论缓存之前,让我们先来讨论讨论另外一个问题:理论和实践.从ahuaxuan接触的程序员来看,有的程序员偏实践,有的程序员偏理论,但是这都是不好的行为,理论和实践同样重要,我们在做很多核心的算法的时候,没有理论根本无从下手,而在我们多年的实践中,不总结理论就不能加深自己的理解.所以理论和实践同等重要. 

缓存是当今各种软件或者硬件系统中不可缺少的技术之一,所以对每个程序员来说都显得异常重要,对ahuaxuan来说亦是如此.如果说用dfa实现文字过滤是从理论到实践,那么本文便是从实践中总结出得理论. 

在讨论缓存功能之前,我们首先来了解一下缓存这个东西本身.ahuaxuan根据自己的经验把缓存问题细分为4类小问题. 

1缓存为什么要存在? 
2缓存可以存在于什么地方? 
3缓存有哪些属性? 
4缓存介质? 

搞清楚这4个问题,那么我们就可以随意的通过应用的场景来判断使用何种缓存了. 

下面ahuaxuan和大家一一分析这4个问题. 
1. 缓存为什么要存在? 
一般情况下,一个网站,或者一个应用,它的一般形式是,浏览器请求应用服务器,应用服务器做一堆计算后再请求数据库,数据库收到请求后再作一堆计算后把数据返回给应用服务器,应用服务器再作一堆计算后把数据返回给浏览器.这个是一个标准流程.但是随着互连网的普及,上网的人越来越多,网上的信息量也越来越多,在这两个越来越多的情况下,我们的应用需要支撑的并发量就越来越多.然后我们的应用服务器和数据库服务器所做的计算也越来越多,但是往往我们的应用服务器资源是有限的,数据库每秒中接受请求的次数也是有限的(谁叫俺们的硬盘转速有限呢).如果利用有限的资源来提供尽可能大的吞吐量呢,一个办法:减少计算量,缩短请求流程(减少网络io或者硬盘io),这时候缓存就可以大展手脚了.缓存的基本原理就是打破上图中所描绘的标准流程,在这个标准流程中,任何一个环节都可以被切断.请求可以从缓存里取到数据直接返回.这样不但节省了时间,提高了响应速度,而且也节省了硬件资源.可以让我们有限的硬件资源来服务更多的用户. 

2 缓存可以存在于什么地方? 
Java代码

  1. 浏览器---浏览器和app之间---分过层的app-数据库  

        浏览器---浏览器和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认为,缓存的使用是架构师的必备技能,好的架构师能够根据数据的类型,业务的场景来准确的判断出使用何种类型的缓存,并且如何使用这种类型的缓存.在缓存的世界里也没有银弹,目前还没有一种缓存可以解决任何的业务场景或者数据类型,如果这种技术出现了,那架构师就又更不值钱了.呵呵.

 

OSCache
  
  OSCache是个一个广泛采用的高性能的J2EE缓存框架,OSCache能用于任何Java应用程序的普通的缓存解决方案。
  
  OSCache有以下特点:
  
  缓存任何对象,你可以不受限制的缓存部分jsp页面或HTTP请求,任何java对象都可以缓存。
  
  拥有全面的API--OSCache API给你全面的程序来控制所有的OSCache特性。
  
  永久缓存--缓存能随意的写入硬盘,因此允许昂贵的创建(expensive-to-create)数据来保持缓存,甚至能让应用重启。
  
  支持集群--集群缓存数据能被单个的进行参数配置,不需要修改代码。
  
  缓存记录的过期--你可以有最大限度的控制缓存对象的过期,包括可插入式的刷新策略(如果默认性能不需要时)。
  
  官方网站 http://www.opensymphony.com/oscache/
  
  Java Caching System 
  
  JSC(Java Caching System)是一个用分布式的缓存系统,是基于服务器的java应用程序。它是通过提供管理各种动态缓存数据来加速动态web应用。
  
  JCS和其他缓存系统一样,也是一个用于高速读取,低速写入的应用程序。
  
  动态内容和报表系统能够获得更好的性能。
  
  如果一个网站,有重复的网站结构,使用间歇性更新方式的数据库(而不是连续不断的更新数据库),被重复搜索出相同结果的,就能够通过执行缓存方式改进其性能和伸缩性。
  
  官方网站 http://jakarta.apache.org/turbine/jcs/
  
  EHCache 
  
  EHCache 是一个纯java的在进程中的缓存,它具有以下特性:快速,简单,为Hibernate2.1充当可插入的缓存,最小的依赖性,全面的文档和测试。
  
  官方网站 http://ehcache.sourceforge.net/
  
  JCache 
  
  JCache是个开源程序,正在努力成为JSR-107开源规范,JSR-107规范已经很多年没改变了。这个版本仍然是构建在最初的功能定义上。
  
  官方网站 http://jcache.sourceforge.net/
  
  ShiftOne 
  
  ShiftOne Java Object Cache是一个执行一系列严格的对象缓存策略的Java lib,就像一个轻量级的配置缓存工作状态的框架。
  
  官方网站 http://jocache.sourceforge.net/
  
  SwarmCache 
  SwarmCache是一个简单且有效的分布式缓存,它使用IP multicast与同一个局域网的其他主机进行通讯,是特别为集群和数据驱动web应用程序而设计的。SwarmCache能够让典型的读操作大大超过写操作的这类应用提供更好的性能支持。
  SwarmCache使用JavaGroups来管理从属关系和分布式缓存的通讯。
  官方网站 http://swarmcache.sourceforge.net
  
  TreeCache / JBossCache 
  JBossCache是一个复制的事务处理缓存,它允许你缓存企业级应用数据来更好的改善性能。缓存数据被自动复制,让你轻松进行JBoss服务器之间的集群工作。JBossCache能够通过JBoss应用服务或其他J2EE容器来运行一个MBean服务,当然,它也能独立运行。
  
  JBossCache包括两个模块:TreeCache和TreeCacheAOP。
  
  TreeCache --是一个树形结构复制的事务处理缓存。
  
  TreeCacheAOP --是一个“面向对象”缓存,它使用AOP来动态管理POJO(Plain Old Java Objects)
  
  注:AOP是OOP的延续,是Aspect Oriented Programming的缩写,意思是面向方面编程。
  
  官方网站 http://www.jboss.org/products/jbosscache
  
  WhirlyCache 

        Whirlycache是一个快速的、可配置的、存在于内存中的对象的缓存。它能够通过缓存对象来加快网站或应用程序的速度,否则就必须通过查询数据库或其他代价较高的处理程序来建立。

       

        Memcached

        Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。Memcached基于一个存储键/值对的hashmap。其守护进程(daemon )是用C写的,但是客户端可以用任何语言来编写,并通过memcached协议与守护进程通信。

       redis

       redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

Redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。它提供了Python,Ruby,Erlang,PHP客户端,使用很方便。

Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制。从盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助。

本文转载自:http://wenwen.sogou.com/z/q183095682.htm

共有 人打赏支持
丈量大地

丈量大地

粉丝 16
博文 52
码字总数 27634
作品 0
都江堰
程序员
私信 提问
加载中

评论(2)

丈量大地
丈量大地

引用来自“zzuqiang”的评论

提供太详细的介绍了,是否忽略了redis?
恩,redis可不能少,我顺便也将Memcached加上了
zzuqiang
zzuqiang
提供太详细的介绍了,是否忽略了redis?
史上最全互联网分布式缓存技术视频教程(redis、memcached、ssdb)

课程主讲: 互联网应用高级架构师 白贺翔 涉及技术: Redis、SSDB、Memcached课程描述: 介绍互联网分布式技术的重要性、背景、应用范围;目前互联网行业使用分布式缓存进行设计的比例,以及...

2846613430
2016/04/19
747
0
Spring支持的CacheManager

数据缓存Cache 为何要用缓存、缓存的目的是为了什么? 我们知道一个程序的瓶颈在于数据库,内存的速度远远大于硬盘的速度,当我们一次又一次 请求数据库或远程服务时会导致大量的时间耗费在数...

恋码之子
2018/12/11
0
0
缓存雪崩,缓存穿透,缓存预热,缓存热备都是什么鬼?

QQ用得起来越少了,现在就加入300+技术微信群,下方公众号回复"微信群"即可加入。 公众号:java技术栈,每日更新 缓存雪崩,缓存穿透,缓存预热,缓存热备是在做缓存设计或者缓存应用时经常遇...

架构之路
2017/11/30
0
0
DotNET企业架构应用实践-系统架构与性能-缓存技术与ORM中的缓存查询技术

系列回顾 在前面的文章DotNET企业架构应用实践-系统架构与性能-理论依据及相关做法一文中我介绍了系统性能优化的理论做了一个概括的介绍,也简单的介绍了性能优化的过程及相关的技术关注点或...

agilelab
2010/10/21
0
0
移动Web加速技术月报第3期

为推进Web技术的发展,Brilliant Open Web 团队特推出每月一期的《移动Web加速技术月报》,该月报将整理较流行的移动Web加速技术,并跟进各项技术的进展和发展方向,以期帮助开发者了解或选用...

BrilliantOpenWeb
2017/12/12
0
0

没有更多内容

加载失败,请刷新页面

加载更多

springmvc源码解析之@EnableWebMvc一

说在前面 本次介绍MvcNamespaceHandler。关注“天河聊架构”微信公众号更多源码解析。 springmvc配置解析 @EnableWebMvc这个注解干了什么,初始化RequestMappingHandlerMapping 先看下这个注...

天河2018
3分钟前
1
0
Druid连接池一个设置引发的血案【abandon connection, open stackTrace】

今天在一台配置很低的机器上运行批量更新的程序~~~ 大概跑了三十分钟~~~这配置~~~这程序~~~ 然后华丽丽的报异常了~~~ 具体异常是这样的, DEBUG: (BaseJdbcLogger.java:132) ooo Using Con...

时刻在奔跑
5分钟前
1
0
idea中配置xml不自动提示解决方案

1.打开设置File-->Settings(或者Ctrl + Alt + S)--->Languages&Frameworks-->Schemas and DTDS 2.选择右上角的“+”进入添加界面 其中URI是你xml文件里引用该xsd文件的地址,File是你本地的...

小橙子的曼曼
11分钟前
1
0
SpringCloud系列第04节之注册中心Eureka高可用

简介 Eureka Server 也支持运行多实例,并以互相注册的方式(即伙伴机制),来实现高可用的部署 即每一台 Eureka 都在配置中指定另一个 Eureka 地址作为伙伴,它在启动时会向伙伴节点获取注册...

吴伟祥
14分钟前
2
0
Logstash读取Kafka数据写入HDFS详解

强大的功能,丰富的插件,让logstash在数据处理的行列中出类拔萃 通常日志数据除了要入ES提供实时展示和简单统计外,还需要写入大数据集群来提供更为深入的逻辑处理,前边几篇ELK的文章介绍过...

运维咖啡吧
16分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部