cache缓存

by admin on 2019年9月24日

通常,应用程序可以将那些频繁访问的数据,以及那些需要大量处理时间来创建的数据存储在内存中,从而提高性能。例如,如果应用程序使用复杂的逻辑来处理大量数据,然后再将数据作为用户频繁访问的报表返回,避免在用户每次请求数据时重新创建报表可以提高效率。同样,如果应用程序包含一个处理复杂数据但不需要经常更新的页,则在每次请求时服务器都重新创建该页会使工作效率低下。

1. 先修知识

  1. b位的二进制数可以表示2^b个数。
    相应的B个数需要log2(B)位来表示。
  2. k代表2的10次方, M代笔2的20次方,G代表2的30次方
  3. 一个字节等于8位,一个字一般为4个字节

  4. 存储器模型

-(NSCache *)cache

注释驱动的 Spring cache
缓存(代码)

在这些情况下,为了帮助您提高应用程序的性能,ASP.NET
使用两种基本的缓存机制来提供缓存功能。第一种机制是应用程序缓存,它允许您缓存所生成的数据,如DataSet或自定义报表业务对象。第二种机制是页输出缓存,它保存页处理输出,并在用户再次请求该页时,重用所保存的输出,而不是再次处理该页。

2.1 cpu与存储器的关系

经典的冯诺依曼模型将计算机分为运算器、存储器、控制器、输入和输出。cpu分为运算器和控制器,cpu需要从内存中读取数据。

{

Spring cache 介绍

应用程序缓存

2.2 cpu与内存的连接

cpu与内存的连接通过数据线连接,主要包括:
地址线,数据线,控制线。各种线的作用如下:

  • 地址线传输地址信息(也就是要读取哪一个地址的数据)
  • 数据线传输读取出的数据
  • 控制线(负责告诉内存是读 还是写)
    注意:
    地址线的位数决定存储器可以寻址的空间,b位的地址可以寻址2^b个地址。
    数据线的位数决定了一次可以读取的数据量的大小。例如8根数据线,一次可以读取8位,也就是一个字节,32根的
    就是一次可以读取4个字节
    假设地址线a根,数据线d根,那么存储器可以存储的位数位: 2^a*d。
    字节数需要除以8

**所以可以将内存想象成二维的矩阵,然后行代表每一个地址,
列代表了这个地址的存储单元每一位保存的数据 **
存储器模型如图所示:

澳门威斯尼人平台登陆 1

QQ图片20161120220202.jpg

以下介绍一个真实的内存过程:

  1. cpu控制器将内存的地址信息放到地址线上
  2. 内存将地址线映射到某一行去。例如三个地址线101的将映射到内存的第5行。
  3. cpu控制器将控制信号(“读”)放到控制信号
  4. 此时开始读, 数据通过数据线到达cpu.

  5. 缓存设计原理

if (_cache == nil) {

缓存是实际工作中非常常用的一种提高性能的方法,
我们会在许多场景下来使用缓存。

应用程序缓存提供了一种编程方式,可通过键/值对将任意数据存储在内存中。使用应用程序缓存与使用应用程序状态类似。但是,与应用程序状态不同的是,应用程序缓存中的数据是易失的,即数据并不是在整个应用程序生命周期中都存储在内存中。使用应用程序缓存的优点是由
ASP.NET
管理缓存,它会在项过期、无效、或内存不足时移除缓存中的项。还可以配置应用程序缓存,以便在移除项时通知应用程序。有关更多信息,请参见缓存应用程序数据。

3.1 缓存的初衷

  • cpu和内存速度之间的差异
  • 存储介质的矛盾(速度,价格,容量)

_cache = [[NSCache alloc]init]澳门威斯尼人平台登陆 ,;

本文通过一个简单的例子进行展开,通过对比我们原来的自定义缓存和 spring
的基于注释的 cache 配置方法,展现了 spring cache
的强大之处,然后介绍了其基本的原理,扩展点和使用场景的限制。通过阅读本文,你应该可以短时间内掌握
spring 带来的强大缓存技术,在很少的配置下即可给既有代码提供缓存能力。

使用应用程序缓存的模式是,确定在访问某一项时该项是否存在于缓存中,如果存在,则使用。如果该项不存在,则可以重新创建该项,然后将其放回缓存中。这一模式可确保缓存中始终有最新的数据。

3.2 缓存可行的原因

  • 局部行原理

_cache.totalCostLimit = 5;//总成本数是5
,如果发现存的数据超过中成本那么会自动回收之前的对象

概述

页输出缓存

3.3 缓存的设计过程

下面都假设一个地址读取一个字节的数据:也就是数据线只有8根

  • 首先设计决定缓存和内存之间移动数据块的大小。假设为B字节的数据,那么就是连续的B个地址的数据放到一个块中去。因为地址是连续的增长的,所以可以使用地址最低b=log2(B)位来代表该块哪一个字节。
  • 确定了块的大小,我们在看通用缓存的设计,缓存被设计成为S组,每组E行,如下图

澳门威斯尼人平台登陆 2

通用缓存结构.PNG

**注意: **这是一种通用的缓冲区的结构,随着M,
E的变化,该结构可以到特殊的情行。例如以下的特殊情况:1. S=1 ; 2. E=1。
该通用缓存结构的规定是:
某一内存块只能放到某一具体的组,但是可以放到该组E行中的任意一行。

  • 现在我们确定了块大小,和使用物理地址的后b位确定一个块中的哪一个字节(我们强调过,一个地址对应一个字节)。现在想像一下,数据块从内存到缓存中的过程,该过程首先要决定将数据放到相应的那个组中去,然后才决定放到哪一行中去。对于S组,我们需要s=log2(S)为来表示放到哪一组中去。

现在我们退出来,从地址的规律的角度思考如何设计该如何决定将数据块放到哪一个缓存组中。
下面是一个5位的地址,共可以表示32个地址,以下是地址的递增到末尾。我们假设一个块保存四个字节,
也就是四个地址的数据,下面我们已经将每块通过空行分割。同样我们假设缓冲区的分为四组,也就是S=4,所以需要两位来表示哪一个组(缓冲区的组数是硬件设计人员决定的,当然可以是任何的组数,但是一般是2的幂次方个。
我们通过下面的地址可以很清晰的看出,

  • 每个块的后两位的十进制就是0-3,确实可以用来标注一个块中的第几个字节,其实这个是因为地址是连续增加,且低位先变化,这个和十进制的递增是一样的。

  • 比较每一块的第一个地址的中间的两个数,
    其也在递增,取值也是0-3,然后同一块内的是相同的,所以使用这两个数作为组号是可行的。

  • 第一块和第五块的数据中间数字会被隐射到同一个组内,因为中间的位的数字是相同的,这时就需要高位来区分。第一块的高位为0,第五块的高位为1,
    高位也被称为标记。 为什么标记一定能保证唯一的确定一个数据块呢?
    首先因为地址是连续增加的,没有重复;当中间的组号再次循环到某一组号时,地址会向前进位,所以标记位会不同。
    标记的位数:地址的位数 – 块偏移的位数 – 组的位数
    注意: 我们是先确定块的大小,进而得到块偏移的位数
    然后由组数,确定组的位数
    最后才是有上述的关系 得到 标记的位数。

标记 组号 块偏移
(1)
0  00  00
0  00  01
0  00  10
0  00  11

0  01  00
0  01  01
0  01  10
0  01  11

0  10  00
0  10  01
0  10  10
0  10  11

0  11  00
0  11  01
0  11  10
0  11  11

(5)
1  00  00
1  00  01
1  00  10
1  00  11

1  01  00
1  01  01
1  01  10
1  01  11

1  10  00
1  10  01
1  10  10
1  10  11

1  11  00
1  11  01
1  11  10
1  11  11
  • 现在我们已经知道放到哪一组中去,下面需要知道放到哪一行中去,因为通用缓冲区约定,放到该组E行中的任意一行,所以当该组中有空闲的空间时,就直接存放就行了。
    问题: 如何判断一个缓冲区有效(即存放有数据)?
    这就是缓冲区中有效位的作用,该位为1表示有效,0表示无效。
    所以只需遍历该组内所有行,若有行中的有效位为0,则将数据放到该行即可
  • 上面我们讨论的是有空闲的时候,那么如果没有空闲,此时需要替换算法来决定将哪一个缓冲块踢掉,替换算法,
    替换算法一般有最近最少使用, FIFO等算法。
    缓冲区设计完成

下面来讨论数据的读取

  • 组选择
    从地址中选择中间的s位,转换为十进制的第i组
  • 行匹配
    从该组中依次匹配每一行,当且仅当有效位和标志位全部一致,才表示数据块匹配
  • 字抽取
    从地址最低的b位,转化到十进制j,表示数据是该块的第j个,读取出来。

_cache.delegate = self;

Spring 3.1
引入了激动人心的基于注释(annotation)的缓存(cache)技术,它本质上不是一个具体的缓存实现方案(例如EHCache
或者
OSCache),而是一个对缓存使用的抽象,通过在既有代码中添加少量它定义的各种
annotation,即能够达到缓存方法的返回对象的效果。

页输出缓存在内存中存储处理后的
ASP.NET 页的内容。这一机制允许 ASP.NET
向客户端发送页响应,而不必再次经过页处理生命周期。页输出缓存对于那些不经常更改,但需要大量处理才能创建的页特别有用。例如,如果创建大通信量的网页来显示不需要频繁更新的数据,页输出缓存则可以极大地提高该页的性能。可以分别为每个页配置页缓存,也可以在
Web.config
文件中创建缓存配置文件。利用缓存配置文件,只定义一次缓存设置就可以在多个页中使用这些设置。

4. 特殊的缓冲区结构

本大节讨论的是对于通用型缓存结构的特化

}

Spring 的缓存技术还具备相当的灵活性,不仅能够使用 SpEL(Spring
Expression Language)来定义缓存的 key 和各种
condition,还提供开箱即用的缓存临时存储方案,也支持和主流的专业缓存例如
EHCache 集成。

页输出缓存提供了两种页缓存模型:整页缓存和部分页缓存。整页缓存允许将页的全部内容保存在内存中,并用于完成客户端请求。部分页缓存允许缓存页的部分内容,其他部分则为动态内容。有关更多信息,请参见缓存 ASP.NET
页。

4.1 直接映射缓冲区

直接映射缓冲区是指 有S组缓冲区,每组只有一个缓冲块。

return _cache;

其特点总结如下:

部分页缓存可采用两种工作方式:控件缓存和缓存后替换。控件缓存有时也称为分段缓存,这种方式允许将信息包含在一个用户控件内,然后将该用户控件标记为可缓存的,以此来缓存页输出的部分内容。这一方式可缓存页中的特定内容,并不缓存整个页,因此每次都需重新创建整个页。例如,如果要创建一个显示大量动态内容的页,其中有些部分为静态内容,这时可以将静态部分放在用户控件中,并允许缓存这些内容。

4.2 组相连

组相连是指有S组,每组E行,E>1.

}

通过少量的配置 annotation 注释即可使得既有代码支持缓存

缓存后替换与控件缓存正好相反。这种方式缓存整个页,但页中的各段都是动态的。例如,如果要创建一个在规定时间段内为静态的页,则可以将整个页设置为进行缓存。如果向页添加一个显示用户名的Label控件,则对于每次页刷新和每个用户而言,Label的内容都将保持不变,始终显示缓存该页之前请求该页的用户的姓名。但是,使用缓存后替换机制,可以将页配置为进行缓存,但将页的个别部分标记为不可缓存。在此情况下,可以向不可缓存部分添加Label控件,这样将为每个用户和每次页请求动态创建这些控件。有关更多信息,请参见缓存 ASP.NET
页的某些部分。

4.3 全相连缓冲区

全相连缓冲区 是指只有一个组

//存数据

支持开箱即用 Out-Of-The-Box,即不用安装和部署额外第三方组件即可使用缓存

根据请求参数缓存页

– (IBAction)addBtnClick:(id)sender

支持 Spring Express Language,能使用对象的任何属性或者方法来定义缓存的
key 和 condition

除缓存页的单一版本外,ASP.NET
页输出缓存还提供了一些功能,可以创建根据请求参数的不同而不同的页的多个版本。有关更多信息,请参见缓存页的多个版本。

{

支持 AspectJ,并通过其实现任何方法的缓存支持

自动移除数据

//NSCache的Key只是对对象进行Strong引用,不是拷贝(和可变字典的区别)

支持自定义 key 和自定义缓存管理者,具有相当的灵活性和扩展性

出于以下原因之一,ASP.NET
可以从缓存中移除数据:

for (NSInteger i = 0; i<10; i++) {

本文将针对上述特点对 Spring cache
进行详细的介绍,主要通过一个简单的例子和原理介绍展开,然后我们将一起看一个比较实际的缓存例子,最后会介绍
spring cache 的使用限制和注意事项。好吧,让我们开始吧

  • 由于服务器上的内存不足,开始一个称为”清理”的过程。

  • 由于缓存中的项已过期。

  • 由于项的依赖项发生了更改。

NSData *data = [NSData
dataWithContentsOfFile:@”/Users/beidou/Desktop/29381f30e924b8995d7368d66a061d950b7bf695.jpg”];

为了帮助管理缓存项,在将项从缓存中移除时,ASP.NET
会通知应用程序。

//cost:成本

清理

[self.cache setObject:data forKey:@(i) cost:1];

清理是在内存不足时从缓存中删除项的过程。如果某些项在一段时间内未被访问,或是在添加到缓存中时被标记为低优先级,则这些项会被移除。ASP.NET
使用CacheItemPriority对象来确定要首先清理的项。有关更多信息,请参见如何:将项添加到缓存中。

NSLog(@”存数据%zd”,i);

过期

}

除了清理外,在缓存项过期时,ASP.NET
会自动从缓存中移除这些项。向缓存添加项时,可以按下表中的描述设置其过期时间。

}

过期类型

说明

可调过期

指定某项自上次被访问后多长时间过期。例如,可以将某项设置为自上次在缓存中被访问后 20 分钟过期。

绝对过期

指定某项在设定的时间过期,而不考虑访问频率。例如,可以将某项设置为在 6:00 PM 过期,或四小时后过期。

//取数据

依赖项

– (IBAction)checkBtnClick:(id)sender

可以将缓存中某一项的生存期配置为依赖于其他应用程序元素,如某个文件或数据库。当缓存项依赖的元素更改时,ASP.NET
将从缓存中移除该项。例如,如果您的网站显示一份报告,该报告是应用程序通过
XML 文件创建的,您可以将该报告放置在缓存中,并将其配置为依赖于该 XML
文件。当 XML 文件更改时,ASP.NET
会从缓存中移除该报告。当代码请求该报告时,代码会先确定该报告是否在缓存中,如果不在,代码会重新创建该报告。因此,始终都有最新版本的报告可用。

{

ASP.NET
缓存支持下表中描述的依赖项。

//    NSLog(@”+++++++++++++++”);

依赖项

说明

键依赖项

应用程序缓存中的项存储在键/值对中。键依赖项允许项依赖于应用程序缓存中另一项的键。如果移除了原始项,则具有键依赖关系的项也会被移除。例如,可以添加一个名为ReportsValid的缓存项,然后缓存若干个依赖于ReportsValid键的报告。当ReportsValid项被移除时,所有依赖于它的缓存报告同样也会从缓存中移除。

文件依赖项

缓存中的项依赖于外部文件。如果该文件被修改或删除,则缓存项也会被移除。

SQL 依赖项

缓存中的项依赖于 Microsoft SQL Server 2005、SQL Server 2000 或 SQL Server 7.0 数据库中表的更改。对于 SQL Server 2005,缓存中的项可依赖于表中的某一行。有关更多信息,请参见使用 SqlCacheDependency 类在 ASP.NET 中缓存。

聚合依赖项

通过使用AggregateCacheDependency类缓存中的项依赖于多个元素。如果任何依赖项发生更改,该项都会从缓存中移除。

自定义依赖项

可以用您自己的代码创建的依赖关系来配置缓存中的项。例如,可以创建一个自定义 Web 服务缓存依赖项,当调用 Web 服务得到一个特定值时,该依赖项就会从缓存中移除数据。

//    for (NSInteger i = 0; i<10; i++) {

应用程序缓存项移除通知

//        NSData *data = [self.cache objectForKey:@(i)];

当项从应用程序缓存中移除时,您可以收到通知。例如,如果有一个需要大量处理时间才能创建的项,当从缓存中移除该项时,您会收到通知以便可以立即替换该项。这样,下次请求该项时,用户便不必等待处理该项。有关更多信息,请参见如何:从缓存中移除项时通知应用程序。

//        if (data) {

在ASP.NET
MVC中,Cache可从HttpContext访问,它是System.Web.Cache的一个实例,目前公司框架中在Web应用时的缓存也是使用这个Cache类

//            NSLog(@”取出数据%zd”,i);

缓存添加

//        }

Cache["CacheItem1"] = "Cached Item 1";Cache.Insert("CacheItem2", "Cached Item 2");//CacheedItem9的值为"Cached Item 9"string CachedItem9 = (string)Cache.Add("CacheItem9","Cached Item 9", null,System.Web.Caching.Cache.NoAbsoluteExpiration,System.Web.Caching.Cache.NoSlidingExpiration,System.Web.Caching.CacheItemPriority.Default,null);

//    }

通过指定依赖项向缓存添加项

NSData *data = [self.cache objectForKey:@(8)];

string[] dependencies = { "CacheItem2" };Cache.Insert("CacheItem3", "Cached Item 3",new System.Web.Caching.CacheDependency(null, dependencies));   Cache.Insert("CacheItem4", "Cached Item 4",new System.Web.Caching.CacheDependency(Server.MapPath("XMLFile.xml")));

if (data) {

添加多个依赖项

NSLog(@”取出数据%@”,data);

System.Web.Caching.CacheDependency dep1 =new System.Web.Caching.CacheDependency(Server.MapPath("XMLFile.xml"));string[] keyDependencies2 = { "CacheItem1" };System.Web.Caching.CacheDependency dep2 =new System.Web.Caching.CacheDependency(null, keyDependencies2);System.Web.Caching.AggregateCacheDependency aggDep =new System.Web.Caching.AggregateCacheDependency();aggDep.Add;aggDep.Add;Cache.Insert("CacheItem5", "Cached Item 5", aggDep);

}

将设有过期策略的项添加到缓存中

}

//下面的代码示例将有一分钟绝对过期时间的项添加到缓存中:即缓存会在插入后一分钟过期Cache.Insert("CacheItem6", "Cached Item 6",null, DateTime.Now.AddMinutes,System.Web.Caching.Cache.NoSlidingExpiration);

//下面的代码示例将有 10 分钟弹性过期时间的项添加到缓存中:即缓存会最后一次访问的10分钟后过期,如每在10分钟内都访问一次,缓存则不会过期。Cache.Insert("CacheItem7", "Cached Item 7",null, System.Web.Caching.Cache.NoAbsoluteExpiration,new TimeSpan(0, 10, 0));

//删除数据

将设有优先级设置的项添加到缓存中

– (IBAction)removeBtnClick:(id)sender

//下面的代码示例将优先级值为 High 的项添加到缓存中:Cache.Insert("CacheItem8", "Cached Item 8",null, System.Web.Caching.Cache.NoAbsoluteExpiration,System.Web.Caching.Cache.NoSlidingExpiration,System.Web.Caching.CacheItemPriority.High, null); 

{

要从缓存中检索数据,应指定存储缓存项的键。不过,由于缓存中所存储的信息为易失信息,即该信息可能由
ASP.NET
移除,因此建议的开发模式是首先确定该项是否在缓存中。如果不在,则应将它重新添加到缓存中,然后检索该项。

[self.cache removeAllObjects];

检索缓存项的值

}

string cachedString;cachedString = (string)Cache["CacheItem"];if (cachedString == null){cachedString = "Hello, World.";Cache.Insert("CacheItem", cachedString);}

#pragma mark ———————-

ASP.NET 缓存中的数据是易失的,即不能永久保存。由于以下任一原因,缓存中的数据可能会自动移除:

#pragma mark NSCacheDelegate

  • 缓存已满。
  • 该项已过期。
  • 依赖项发生更改。

//即将回收对象的时候调用该方法

从缓存中显式删除项

-(void)cache:(NSCache *)cache willEvictObject:(id)obj

Cache.Remove("MyData1"); 

{

从缓存中移除项时通知应用程序

NSLog(@”回收%zd”,[obj length]);

//在Add方法中添加有个参数是传入一个CacheItemRemovedCallback的委托,这个委托在缓存被清理时调用,Cache.Add("MyReport",CreateReport(), null, DateTime.MaxValue,new TimeSpan(0, 1, 0),System.Web.Caching.CacheItemPriority.Default,ReportRemovedCallback); 

}

***委托的定义如下,CacheItemRemovedReason是一个枚举,传递缓存被移除的原因,


public delegate void CacheItemRemovedCallback(string key, object value, CacheItemRemovedReason reason);

澳门威斯尼人平台登陆 3

在Web.Config中,对缓存设置如下

<caching><!--定义全局应用程序缓存设置。--><cache<!-- 是否当计算机处于内存压力下时是否禁止执行缓存内存回收。-->disableMemoryCollection = "false"<!--是否禁用缓存过期。如果禁用,则缓存项不会过期,并且不会对过期缓存项执行后台清理。-->disableExpiration = "false"<!--指示在缓存开始刷新过期项并尝试回收内存之前应用程序的最大专用字节大小。此限制同时包括缓存所使用的内存量以及运行应用程序的正常内存开销。如果设置为零,则指示 ASP.NET 将使用自己的试探法确定何时开始回收内存。-->privateBytesLimit = "0"<!--指示在缓存开始刷新过期项并尝试回收内存之前应用程序可使用的最大计算机物理内存百分比。该内存使用率同时包括缓存使用的内存以及正运行的应用程序的正常内存使用率。如果设置为零,则指示 ASP.NET 将使用自己的试探法确定何时开始回收内存。-->percentagePhysicalMemoryUsedLimit = "90"<!--指示两次轮询应用程序专用字节内存使用量之间的时间间隔。-->privateBytesPollTime = "00:02:00"/>   <outputCache enableOutputCache = "true"enableFragmentCache = "true"sendCacheControlHeader = "true"omitVaryStar = "false" ></outputCache><!--指定应用程序范围的输出缓存设置。-->   <outputCacheSettings><outputCacheProfiles><add name = ""enabled = "true"duration = "-1"location = ""sqlDependency = ""varyByCustom = ""varyByControl = ""varyByHeader = ""varyByParam = ""noStore = "false"/></outputCacheProfiles></outputCacheSettings><!--指定可以应用于应用程序中页的输出缓存设置。-->   <outputCacheSettings><outputCacheProfiles><clear /></outputCacheProfiles></outputCacheSettings>   <sqlCacheDependency enabled = "true"pollTime = "60000"><databases><add name = ""connectionStringName = ""pollTime = "60000"/></databases></sqlCacheDependency><!--为 ASP.NET 应用程序配置 SQL 缓存依赖项。-->   </caching>

针对上面以介绍应用程序缓存为主。只有cache节点对其有影响。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图