我的应用程序包括客户端、Web 层(负载平衡)、应用程序层(负载平衡)和数据库层。Web 层向客户端公开服务,并将调用转发到应用程序层。然后应用层对数据库执行查询(使用 NHibernate)并返回结果。
数据主要是读取,但写入却相当频繁,尤其是当新数据进入系统时。通常情况下,数据是聚合的,这些聚合返回给客户端 - 而不是原始数据。
通常,用户会对最近数据的聚合感兴趣——比如过去一周的数据。因此,对我来说,引入一个包含过去 7 天所有数据的缓存是有意义的。我不能只在加载实体时缓存它们,因为我需要聚合一系列实体,并且该范围由客户端以及其他复杂情况(例如过滤器)决定。我需要知道 - 在给定的时间范围内 - 该范围内的所有数据是否都在缓存中。
在我理想的幻想世界中,我的服务根本不需要改变:
public AggregationResults DoIt(DateTime starting, DateTime ending, Filter filter)
{
// execute HQL/criteria call and have it automatically use the cache where possible
}
将有一个单独的过滤层连接到 NHibernate 中,并智能且透明地确定 HQL/条件查询是否可以针对缓存执行,并且仅在必要时才进入数据库。如果所有数据都在缓存中,它会查询缓存数据本身,有点像内存数据库。
然而,在第一次检查中,NHibernate 的二级缓存机制似乎并不适合我的需要。我想做的是:
- 将其配置为始终在缓存中保留最近 7 天的数据。例如。“对于这个表,缓存该字段在 7 天前和现在之间的所有记录。”
- 具有手动维护缓存的能力。当新数据进入系统时,如果我可以直接将其放入缓存而不是等到缓存失效,那就太好了。同样,当数据超出时间段时,我希望能够从缓存中提取它。
- 让 NHibernate 智能地了解它何时可以直接从缓存中提供查询,而不是完全访问数据库。例如。如果用户请求过去 3 天的数据聚合,则该聚合应直接从缓存中计算,而不是接触数据库。
现在,我很确定#3 要求太多了。即使我可以在缓存中填充所需的所有数据,NHibernate 也不知道如何有效地查询这些数据。它实际上必须遍历所有实体以区分哪些与查询相关(老实说,这可能很好)。此外,它还需要实现 NHibernate 的查询引擎,该引擎针对对象而不是数据库执行。但我可以做梦,对吧?
假设 #3 要求太多,我需要在我的服务中使用一些逻辑,如下所示:
public AggregationResults DoIt(DateTime starting, DateTime ending, Filter filter)
{
if (CanBeServicedFromCache(starting, ending, filter))
{
// execute some LINQ to object code or whatever to determine the aggregation results
}
else
{
// execute HQL/criteria call to determine the aggregation results
}
}
这并不理想,因为每个服务都必须是缓存感知的,并且必须复制聚合逻辑:一次用于通过 NHibernate 查询数据库,一次用于查询缓存。
也就是说,如果我至少可以将相关数据存储在 NHibernate 的二级缓存中,那就太好了。这样做将允许其他服务(不进行聚合)透明地从缓存中受益。如果我决定在系统的其他地方需要二级缓存,它还将确保我不会在缓存的实体上加倍(一次在二级缓存中,一次在我自己的单独缓存中)。
我怀疑如果我可以ICache
在运行时获得实现,我需要做的就是调用该Put()
方法将我的数据粘贴到缓存中。但这可能是在危险的地方...
谁能提供关于 NHibernate 的二级缓存机制是否可以满足我的任何要求的任何见解?还是我应该推出自己的解决方案并完全放弃 NHibernate 的二级缓存?
谢谢
PS。我已经考虑过使用多维数据集更快地进行聚合计算,但这仍然让我将数据库作为瓶颈。除了缓存之外,我还可以使用多维数据集,但缺少缓存是我现在最关心的问题。