使用AppFabric Cache分页,列出和分组查询

时间:2011-01-26 10:48:22

标签: caching appfabric distributed-caching

我阅读了很多关于AppFabric缓存的文档,但其中大多数都涵盖了简单的场景。     例如,将城市列表数据或购物卡数据添加到缓存。     但我需要将产品目录数据添加到缓存中。

我有4张桌子:

产品(100万行),ProductProperty(2500万行),属性(100行),PropertyOption(300行)

  • 我显示分页搜索结果,查询Product和ProductProperty表的一些过滤器。
  • 我正在创建搜索结果集的标准集。例如(4项新产品,34项电话,26项预订等)
  • 我查询使用IsNew,CategoryId,PriceType等列对Product表进行分组。
    以及使用PropertyId和PropertyOptionId列对ProductProperty表进行分组以获取具有多少项的属性的另一个查询

因此,为了显示搜索结果,我对搜索结果进行了一次查询,为创建条件列表(有计数)进行了2次

搜索结果查询占用0.7秒,2个分组查询占用总共1.5秒。 当我运行负载测试时,我每秒达到7个请求,并且由于db无法给出响应,因此%10会被丢弃。

这就是我想要缓存产品和属性记录的原因。

如果我按照以下项目(在AppFabric中);

  • 创建命名缓存
  • 为产品目录数据创建区域(包含100万行的表和具有2500万行的属性表)
  • 标记用于查询数据和分组的项目。

我可以查询一些标签并获得第1页或第2页的结果吗? 我可以查询一些标签并获取一些分组结果的计数。 (显示带计数的过滤器选项) 我需要3台服务器吗?我可以提供只有一个appfabric服务器的解决方案(当然我知道风险。) 您知道任何文章或任何文件解释了这些情景吗?

感谢。

注意:

一些额外的测试: 我向缓存添加了大约30,000个项目,其大小为900 MB。 当我运行getObjectsInRegion方法时,花了大约2分钟。 “IList> dataList = this.DataCache.GetObjectsInRegion(region).ToList();” 问题是转换为IList。如果我使用IEnumerable它非常有效。但是如何在不将其转换为我的类型的情况下获得分页或分组结果?

另一项测试:

我尝试使用30.000产品项目进行分组计数,获得分组结果需要4秒。例如GetObjectByTag(“IsNew”)。Count()和其他近50个查询。

1 个答案:

答案 0 :(得分:2)

遗憾的是,V1中的AppFabric没有分页API。任何批量API(如GetObjectsByTag)都将在服务器上执行查询,并将所有匹配的缓存条目流回客户端。从那里你可以明显地在IEnumerable上使用你想要的任何LINQ运算符(例如Skip/Take/Count),但要注意你始终从中提取完整的结果集服务器

我个人希望AppFabric V2能够通过IQueryable而不是IEnumerable提供支持,这将提供远程服务器的完整请求的能力,因此它可以在返回客户端之前将结果分页,就像LINQ2SQL一样或ADO.NET EF。

目前,根据应用程序的功能,一个可能的解决方案是,在将项目注入缓存时,您实际上可以计算某种分页。您可以构建表示每个页面的实体键的有序列表,并将它们作为单个条目存储在缓存中,您可以在一个请求中提取,然后单独(并行)或批量从缓存中获取列表中的项目并将它们连接在一起使用内存LINQ查询。如果您想将CPU换成内存,只需缓存完整实体的实际列表而不是ID,并且必须为实体进行连接。

显然,您必须提出某种键控机制,以根据传入的搜索条件从缓存中快速提取这些对象列表。像这样的某种键控可能会起作用:

private static string BuildPageListCacheKey(string entityTypeName, int pageSize, int pageNumber, string sortByPropertyName, string sortDirection)
{
   return string.Format("PageList<{0}>[pageSize={1};pageNumber={2};sortedBy={3};sortDirection={4}]", entityTypeName, pageSize, pageNumber, sortByPropertyName, sortDirection);
}

您可能需要考虑使用单独的进程或工作线程来执行此类操作,该进程或工作线程使缓存保持最新而不是按需执行,并强制用户等待缓存条目尚未填充。

此方法最终是否适合您取决于您​​的应用程序和数据的几个因素。如果它不完全适合你的场景,那么它至少可以帮助你转变思维方式来解决问题。