7.3 [Enerprise Library]关键场景

本文是Enterprise Library 3.1 帮助文档中文翻译 的一部分。

本节描述了开发人员在存储数据到缓存时必须解决的绝大多数常规情况。每个场景解释了任务,为任务给出了一个真实世界的情况,并包含了如果使用缓存应用程序块完成任务的代码示例。场景分为两节,第一节示范了基本的缓存操作:

  • 添加条目到缓存。描述了如何使用 Add 方法添加条目到缓存中,它也允许设置条目的过期策略(用于超期处理)和优先级(用于清理处理)。

  • 从缓存中移除条目。描述了如何使用 Remove 方法从缓存中删除条目。

  • 从缓存中获取条目。描述了如何使用 GetData 方法。

  • 清除缓存。描述了如何清除缓存,使用 Flush 方法来清空它。

第二节,加载缓存,示范了主动和被动的加载。

添加条目到缓存

缓存保存创建或传输昂贵的条目。例如,在一个零售业应用程序中,产品列表必须从数据访问组件传输到用户接口缓存,以使产品列表可能可以显示给用户。数据表示了真实世界的业务实体,如产品或订单。要提高性能,这些条目的某些必须添加到缓存中。

典型目标

在此场景中,要添加条目到缓存中,也要为超期处理设置过期周期和为清理处理设置优级。

解决方案

使用由 CacheManager 类提供的 add 方法。CacheManager 类添加新的条目到缓存中。如果没有明确的设置超期周期和优先级属性,它们将设置为默认设置。在此用例中的默认设置为 NeverExpiredNormal 。如果另一个使用同样的键的条目已存在,那个条目将在新条目添加前被删除。如果在此过程中发生错误,缓存将被恢复到它的初始状态。

快速入门

如何使用 Add 方法的其他例子,请参见快速入门漫游,漫游:添加条目到缓存。

使用 Add 方法

下列代码展示了如何使用 Add 方法。它创建了一个 Product 类型的对象,然后将它添加到了缓存中,并带有清理优先级2、一条在条目过期时不刷新它的指令以及从条目最后一次被访问起的5分钟的过期时间。

注意

代码不包含 Product 类的定义。

例 7.5. C#

CacheManager productsCache = CacheFactory.GetCacheManager();

string id = "ProductOneId";
string name = "ProductXYName";
int price = 50;

Product product = new Product(id, name, price);

productsCache.Add(product.ProductID, product, CacheItemPriority.Normal, null, new SlidingTime(TimeSpan.FromMinutes(5)));

例 7.6. Visual Basic .NET

Dim productsCache As CacheManager = CacheFactory.GetCacheManager()

Dim id As String = "ProductOneId"
Dim name As String = "ProductOneName"
Dim price As Integer = 50

Dim newProduct As Product = New Product(id, name, price)

productsCache.Add(newProduct.ProductID, newProduct, CacheItemPriority.Normal, Nothing, New SlidingTime(TimeSpan.FromMinutes(5)))

刷新移除的条目

Add 方法允许指定一个实现了 ICacheItemRefreshAction 接口的对象。对象的 Refresh 方法在某个条目从缓存中移除时被调用,这提供了刷新缓存中条目的机会。

例 7.7. C#

[Serializable]
public class ProductCacheRefreshAction : ICacheItemRefreshAction
{
public void Refresh(string key, object expiredValue, CacheItemRemovedReason removalReason)
{
// Item has been removed from cache. Perform desired actions here, based on
// the removal reason (for example, refresh the cache with the item).
}
}

例 7.8. Visual Basic .NET

<Serializable()> _
Public Class ProductCacheRefreshAction
Implements ICacheItemRefreshAction

Public Sub Refresh(ByVal removedKey As String, ByVal expiredValue As Object, ByVal removalReason As CacheItemRemovedReason) Implements ICacheItemRefreshAction.Refresh
' Item has been removed from cache. Perform desired actions here, based on
' the removal reason (for example, refresh the cache with the item).
End Sub
End Class

接收条目从缓存中移除的通知要求在调用的 Add 方法中指定实现了 ICacheItemRefreshAction 接口的类,就像下列代码一样。

例 7.9. C#

CacheManager productsCache = CacheFactory.GetCacheManager();

string id = "ProductOneId";
string name = "ProductXYName";
int price = 50;

Product product = new Product(id, name, price);

productsCache.Add(product.ProductID, product, CacheItemPriority.Normal, new ProductCacheRefreshAction(), new SlidingTime(TimeSpan.FromMinutes(5)));

例 7.10. Visual Basic .NET

Dim productsCache As CacheManager = CacheFactory.GetCacheManager()

Dim id As String = "ProductOneId"
Dim name As String = "ProductOneName"
Dim price As Integer = 50

Dim newProduct As Product = New Product(id, name, price)

productsCache.Add(newProduct.ProductID, newProduct, CacheItemPriority.Normal, New ProductCacheRefreshAction, New SlidingTime(TimeSpan.FromMinutes(5)))

使用提示

下面有一些附加信息:

  • 当添加任何条目到配置为使用数据库后端存储的缓存中时,条目的类型必须是可串行化的。

  • 在使用数据库做为后端存储时,实现了 ICacheItemRefreshAction 接口的类必须是可串行化的。

  • 关于串行化的更多消息,请参见MSDN上的 Object Serialization in the .NET Framework

加载缓存

在使用缓存的数据前,必须首先加载数据到缓存中。例如,在零售业应用程序中,可能要加载多种产品或全部产品的数据到缓存中。

典型目标

在此场景中,要添加数据到缓存中以提高应用程序的性能。

解决方案

有两种方法可以用于加载数据:

主动加载

此方法为应用程序或进程的生命周期获取所有需要的数据( required state ) 然后缓存它。

被动加载

此方法在应用程序请求时才获取需要的数据,然后缓存它以备将来的请求。

主动缓存数据

可以主动的缓存数据来为应用程序和进程主动的获取所有需要的数据( required state ) ,典型的是应用程序启动时,并在应用程序和进程的生命期内缓存它。

主动加载的优点

因为可以保证数据已加载进缓存,理论不用检查数据是否已在缓存中,因为缓存可能会被清空,所以在获取它之前检查它是否已存在缓存中。

应用程序性能有所提升,因为在主动加载数据到缓存时缓存的操作是被优化了的。应用程序响应时间也有所改善,因为所有数据已被缓存。

主动加载的缺点

主动加载在绝大多数已优化的系统中是不起作用的,因为许多数据即使不需要也被加载到了缓存中。例如,一个应用程序包含100个进程,每个进程需要缓存中的某些条目。如果用户运行了这个应用程序,但只激活了一个进程,缓存的上百个条目是不需要的。

主动缓存可能导致比常规技术实现更为复杂。使用常规技术,每个条目都与已知的程序流同步获取。使用主动缓存需要用几个线程工作,因此很难用应用程序的主线程同步线程、保持线程状态的跟踪以及在异步程序模型中处理异常。

主动加载的建议

如果没有正确的使用主动加载,应用程序可能初始化非常慢。当实现主动缓存时,在应用程序初始化或每个进程初始化时尽可能多的加载数据。可以使用异步程序模型来在后台进程中加载数据。

主动缓存推荐使用在有一个或多个下列特点的情形:

  • 使用已知更新周期的静态或半静态数据(state)。如果在其他场景中使用,数据在未使用前可能已过期。

  • 使用已知生命期的数据(state)。

  • 使用已知大小的数据(state)。如果在不知道数据大小的时候使用主动缓存数据加载,就可能会耗尽系统资源,必须尝试不使用不拥有的资源。

  • 拥有有问题的资源,如缓慢的数据库、缓慢的网络或者不可靠的 Web 服务。就可以使用此技术来主动获取所有的数据( state ),缓存它,并尽可能的使用缓存来工作。

被动缓存数据

可以被动的缓存数据来获取应用程序请求的数据,并缓存它以备后用。

被动加载的优点

因为在应用程序启动时没有加载许多数据,系统资源将不会被误用。此方法导致了一个优化的缓存系统,因为仅保存了需要的条目。

被动加载的缺点

性能在任何数据首次请求时都可能降低,因为它必须从数据源中加载,它没有从缓存中获取。还有,在使用前必须检查条目是否已存在于缓存中,在每个服务客户端检查此可以导致代码中过度的条件逻辑。

被动加载的建议

被动加载推荐使用有下列一个或多个特点的情形中:

  • 使用许多数据,没有足够的资源来为整个应用程序缓存所有的数据。

  • 使用可靠、敏感( responsive ) 资源,如数据库、网络或 Web 服务,这将不影响应用程序的稳定性和性能。

  • 对应用程序初始化过程中缓存数据不可用感兴趣。例如,此数据可能受用户输入(如普通搜索查询)或用户特定数据如用户配置的影响。

关于主动加载和被动加载的更多信息,请参见Application Architecture for .NET: Designing Applications and Services

快速入门

如何主动或被动的加载缓存的其他示例,请参见快速入门漫游,漫游:加载缓存。

加载示例

下载代码示范了一种主动加载缓存的方法。它读取了保存在主数据源中的数据(在此是一个 XML 文件),并且马上将它保存以缓存中,使用 Add 方法。GetProductList 方法是快速入门的一部分,而不是缓存应用程序块的一部分。

例 7.11. C#

public List<Product> GetProductList()
{
// This returns a list of product objects.
}

public void LoadAllProducts()
{
CacheManager cache = CacheFactory.GetCacheManager();

List<Product>list = GetProductList();

for (int i = 0; i < list.Count; i++)
{
Product product = list[i];
cache.Add(product.ProductID, product);
}
}

例 7.12. Visual Basic .NET

Public Function GetProductList() As List(Of Product)
' This returns a list of product objects.
End Function

Public Sub LoadAllProducts()
Dim cache As CacheManager = CacheFactory.GetCacheManager()

Dim list As List(Of Product) = GetProductList()
Dim i As Integer
For i = 0 To list.Count - 1
Dim product As Product = list(i)
cache.Add(product.ProductID, product)
Next
End Sub

下列代码示范了一种被动加载缓存的方法。它先检查看条目时否已在缓存中。如果没有,它从主数据源(在此是一个 XML 文件) 中获取它,并使用 Add 方法添加它到缓存中。GetProductByID 方法是快速入门的一部分,而不是缓存应用程序块的一部分。

例 7.13. C#

public Product GetProductByID(string anID)
{
// This returns a product object with the specified ID.
}

public Product ReadProductByID(string productID)
{
CacheManager cache = CacheFactory.GetCacheManager();

Product product = (Product)cache.GetData(productID);

// Does our cache already have the requested object?
if (product == null)
{
// The requested object is not cached, so retrieve it from
// the data provider and cache it for further requests.
product = this.dataProvider.GetProductByID(productID);

if (product != null)
{
cache.Add(productID, product);
}
}
return product;
}

例 7.14. Visual Basic .NET

Public Function GetProductByID(ByVal anID As String) As Product
' This returns a product object with the specified ID.
End Function

Public Function ReadProductByID(ByVal productID As String) As Product
Dim cache As CacheManager = CacheFactory.GetCacheManager()
Dim product As Product = DirectCast(cache.GetData(productID), Product)

' Does our cache already have the requested object?
If (product Is Nothing) Then

' The requested object is not cached, so retrieve it from
' the data provider and cache it for further requests.
product = GetProductByID(productID)

If (Not product Is Nothing) Then
cache.Add(productID, product)
End If
End If
Return product
End Function

清空数据

清空可以管理缓存的条目以确定存储、内存和其他资源有效的利用。清空移除缓存中所有的条目,包括那些未过期的。例如,在零售业应用程序中,缓存的数据不再可用,这因为用户的选择或因为用户注销。

典型目标

在此场景中,要从缓存中移除所有条目。

解决方案

关于如何使用 Flush 方法的其他示例,请参见快速入门漫游,漫游:清空缓存。

使用 Flush 方法

下列代码展示了如何使用 Flush 方法。添加代码到响应清空缓存请求的方法。

例 7.15. C#

CacheManager productsCache = CacheFactory.GetCacheManager();

// Operations on the cache

productsCache.Flush();

例 7.16. Visual Basic .NET

Dim productsCache As CacheManager = CacheFactory.GetCacheManager()

' Operations on the cache

productsCache.Flush()

从缓存中移除缓存

清理和超期进程自动根据条目的优先级和过期策略从缓存中移除条目,也可以从缓存中移除指定的条目。例如,在一个零售业应用程序中,某些数据不再适用,这依赖物用户做出的选择。

典型目标

在此场景中,要从缓存中移除指定的条目。

解决方案

使用 CacheManager 类提供的 Remove 方法。Remove 方法从缓存中移除指定的条目。

快速入门

如何使用 Remove 方法的其他示例,请参见快速入门漫游,漫游:从缓存中移除条目。

使用 Remove 方法

下列代码展示了如何使用 Remove 方法。

例 7.17. C#

public void Remove(CacheManager cache, string key)
{
cache.Remove(key);
}

例 7.18. Visual Basic .NET

Public Sub Remove(ByVal cache As CacheManager, ByVal key As String)
cache.Remove(key)
End Sub

从缓存中获取条目

存储在缓存中的数据必须获取以被显示或处理。例如,在一个零售业应用程序中,可能要从分类中显示产品列表。

典型目标

在此场景中,要从缓存中获取特定的条目。

解决方案

使用由 CacheManager 类提供的 GetData 方法,它返回与指定的键关联的值。

快速入门

如何使用 GetData 方法的其他示例,请参见快速入门漫游,漫游:从缓存获取条目。

使用 GetData 方法

下列代码展示了如何使用 GetData 方法。添加代码到响应从缓存中获取条目的请求的方法中。

例 7.19. C#

// Read the item from the cache. If the item is not found
// in the cache, the return value will be null.
public Product GetProduct(CacheManager cache, string key)
{
return (Product)cache.GetData(key);
}

例 7.20. Visual Basic .NET

' Read the item from the cache. If the item is not found
' in the cache, the return value will be null.
Public Function GetProduct(ByVal cache As CacheManager, ByVal key As String) As Product
Return DirectCast(Cache.GetData(key), Product)
End Function
posted @ 2007-10-27 03:30  Dorian Deng  阅读(1375)  评论(2编辑  收藏  举报