毛毛的小窝 — 关注技术交流、让我们一起成长

导航

Enterprise Library—缓存应用程序块

 

Enterprise Library缓存应用程序块

前言

在介绍Cache Application Block之前,我们现了解一下缓冲存储。缓冲存储分为内存驻留型缓冲和磁盘驻留型缓冲。

1)内存驻留型缓冲:

内存驻留型缓冲的典型应用:应用程序经常使用同样的数据;一个应用程序经常需要重新获得数据。

2)磁盘驻留型缓冲:

磁盘驻留型缓冲的典型应用:数据量比较大,同时,从应用服务提供商(例如数据库)重新获取数据,开销比较大;在缓冲的生命周期中,必须经历系统的重新启动。

一、为什么需要Cache Application Block

在构建企业级分布式应用程序时,架构师和开发人员面临着许多难题。缓存可以帮助您克服其中的一些难题,包括:

性能:通过存储与数据使用者尽可能接近的相关数据,缓存可以提高应用程序的性能。这样可以避免重复进行数据创建、处理和传输。

可伸缩性:在缓存中存储信息有助于节省资源,并且可以随着应用程序需求的增加来提高可伸缩性

可用性:通过将数据存储在本地缓存中,应用程序可以承受系统的故障,例如网络等待时间、Web 服务问题以及硬件故障

适用的情况:

1)必须重复访问静态数据或极少更改的数据

2)在创建、访问或传输方面,数据访问的开销很高

3)即使在源(例如服务器)不可用时,数据也必须始终可用

缓冲应用程序块可应用于以下任何一种应用程序类型:

Windows 窗体

控制台

Windows 服务

企业服务

ASP.NET Web 应用程序或 Web 服务

应该将缓存应用程序块部署在单个应用程序域中。每个应用程序域都可以有一个或多个缓存(可以有也可以没有后备存储)。缓存不能在不同的应用程序域之间共享。

缓存应用程序块的性能已优化,并且是线程安全和异常安全的。您可以对它进行扩展,以包括您自己的过期策略和后备存储。

二、什么是Cache Application Block

企业库缓冲应用程序块提供了一些方便易用的,可扩展的缓冲机制,可让开发人员将本地缓存集成到其应用程序中。它支持内存缓存和后备存储(可选),后者可以是企业程序库数据访问应用程序块或独立存储方式(Isolated Storage)。应用程序块无需修改即可使用,它还可以提供检索、添加和删除缓存数据所需的全部功能。可配置的过期时间与清除策略也是应用程序块的一部分功能。

在这里顺便说一下缓冲存储的几点建议:

缓冲通常在内存中

还经常需要有后端存储

没有后端存储,是不容易实现持久化的

因此持久化存储是非常必要的

持久化的后端存储

当需要被缓冲的数据的生命周期中不可避免的需要经历进程或系统的重启时

支持使用隔离式存储和数据库方式(Data Access Application Block)

内容需要和缓冲一致(Rollback)

内容是从缓冲的初始化时装载到后端的

隔离式存储

支持基于用户和程序集的隔离机制

不需要Unique Path

避免Hard Code

Caching Application Block 提供了分区机制,在一个应用程序中,并存多个cache managers

不支持,也不应该支持多个由多个Cache manager共享存储或分区

三、设计Cache Application Block

Caching Application Block在设计时要达到的目标:

1)        提供大小合适易于管理的一族API

2)        允许开发者将标准的缓存操作集成到他们的应用中,而无需学习程序块内在的工作机制;

3)        利用Enterprise Library Configuration工具,可以很容易的实现配置;

4)        线程安全;

5)        保证后备存储完整无缺;

6)        保证内存缓冲和后备存储同步;

Caching Application Block主要类之间的关系图:

 


四、
开始实践

这里我们以浏览员工的信息为例来说明缓存应用程序块的应用。在浏览员工信息的过程中,员工的照片是最占用时间的,这里我们为了增强效果,在获取员工照片时,我们给它延迟一段时间,使效果更加明显。

 

如上图所示:在浏览员工的工程中,Form利用EmployeeService类来获取要显示的数据。EmployeeService 只是直接委托EmployeeDataProvider类。

简单的运用

1)              在项目中引用Microsoft.Practices.EnterpriseLibrary.Caching.dll,在EmployeeService中添加using Microsoft.Practices.EnterpriseLibrary.Caching;

2)              GetEmployeePhoto方法是获取员工的照片

 

public static Bitmap GetEmployeePhoto(Guid employeeId)

{

    
byte[] photoData = null;

 

    
// TODO: 增加照片缓存

 

    
// 尝试从缓存中获取

    CacheManager cache 
= CacheFactory.GetCacheManager();

    photoData 
= (byte[])cache[employeeId.ToString()];

 

    
// 缓存中不存在,直接从dataProvider中获取

    
if (photoData == null)

    
{

        EmployeeDataProvider dataProvider 
= new EmployeeDataProvider();

        photoData 
= dataProvider.GetEmployeePhotoData(employeeId);

              
// 将新的照片加入到缓存

        cache.Add(employeeId.ToString(), photoData);

    }


 

    
// No data found.

    
if (photoData == null)

        
return null;

 

    
// Convert bytes to Bitmap

    
using (MemoryStream ms = new MemoryStream(photoData))

    
{

        
return new Bitmap(ms);

    }


}


(注:和其他的企业库一样,这个方法利用了工厂模型来创建一个新的CacheManager实例。这种方式依赖与配置,纯粹in-memory或被物理存储介质的支持。每个员工信息可以利用索引从缓存中取出,也可以利用Add方法添加到缓存中。在这个过程中,没有说明内存详细的生命周期。)

3)              清空缓存

 

public static void ClearCache()

{

    
// TODO: 清空缓存

    CacheManager cache 
= CacheFactory.GetCacheManager();

    cache.Flush();

}


(注:这种方法将会使所有存在缓存中的员工信息清除。)

持久化缓存

现在说说利用持久化后备存储和生命周期来进行离线缓存。

1)       EmployeeService添加using Microsoft.Practices.EnterpriseLibrary.Caching.Expirations;

2)        GetContactDetails方法用来获取员工的信息,不包括照片。

 

public static EmployeesDataSet GetContactDetails()

{

    EmployeesDataSet dsEmployees 
= null;

 

    
// TODO:增加持久化缓存和过期时间

 

    
// 尝试从缓存中取员工信息

    CacheManager cache 
= CacheFactory.GetCacheManager();

    dsEmployees 
= (EmployeesDataSet)cache[CACHE_KEY];

 

    
// 如果缓存中没有而且连接正常,从dataProvider 取信息。

    
if (dsEmployees == null && ConnectionManager.IsOnline)

    
{

        EmployeeDataProvider dataProvider 
= new EmployeeDataProvider();

        dsEmployees 
= dataProvider.GetEmployees();

 

        
// 设置过期时间

        AbsoluteTime expiry 
= new AbsoluteTime(new TimeSpan(2000));

        cache.Add(CACHE_KEY, dsEmployees,

            CacheItemPriority.High, 
null,

            
new ICacheItemExpiration[] { expiry });

    }


 

    
return dsEmployees;

}


后台缓存

 

private static void PopulateCache()

{

    
byte[] photoData = null;

 

    EmployeesDataSet dsEmployees 
= GetContactDetails();

 

    
if (dsEmployees == null)

        
return;

 

    CacheManager cache 
= CacheFactory.GetCacheManager();

 

    
foreach (EmployeesDataSet.EmployeesRow employee in dsEmployees.Employees)

    
{

        
if (!cache.Contains(employee.EmployeeID.ToString()))

        
{

            EmployeeDataProvider dataProvider 
= new EmployeeDataProvider();

            photoData 
= dataProvider.GetEmployeePhotoData(employee.EmployeeID);

            cache.Add(employee.EmployeeID.ToString(), photoData);

        }


    }


}


 

private delegate void PopulateCacheDelegate();

 

public static void BeginBackgroundLoad()

{

    
if (!ConnectionManager.IsOnline)

        
return

 

    PopulateCacheDelegate mi 
= new PopulateCacheDelegate(PopulateCache);

    mi.BeginInvoke(
nullnull);

}


 


(注:
BeginBackgroundLoad方法利用委托开始在后台线程中调用PopulateCache方法。PopulateCache方法获取所有员工的信息并写入缓存中。如果用户增加或删除数据集种的记录,这种行为实际使并不是安全的。当我们利用缓存的时候,缓冲程序集给我们保证了线程的安全,所以同时在多线程下也可以安全的访问。)

配置文件

1)打开项目的配置文件,新建一个缓存应用程序块

 


2
)通常情况下,默认即可。

 

 

3)新建一个隔离式存储

 


4
)将隔离名称设置为EmployeeBrowser

 

 

写在后面

关于缓存应用程序块,还有很多功能有待解说,希望大家将自己的好的例子拿出来和大家分享。

参考资料

Download Enterprise Library and related resources from:

http://msdn.microsoft.com/practices

http://msdn.microsoft.com/library/?url=/library/en-us/dnpag2/html/EntLib2.asp

Join the Enterprise Library Community at:

http://practices.gotdotnet.com/projects/entlib

Read blogs from the Enterprise Library team at:

http://msdn.microsoft.com/practices/Comm/EntLibBlogs/ 

posted on 2006-07-04 16:29  mjgforever  阅读(2659)  评论(3编辑  收藏  举报