在研究nhibernate中二级缓存提供的可能性时,我测试了一些实现。目前结果非常出乎意料,我怀疑我的期望是否错误。
首先将4 * 20000个具有一个字符串属性的简单对象插入到数据库中,然后四个线程通过object-id(session.Get<SimpleObj>(id)
)获取它们。每个线程只访问它创建的ID。访问模式是随机的,获取1000个对象,然后重新创建会话。
while (true)
{
using (var session = sf.OpenSession())
using (var tx = session.BeginTransaction())
{
for (int i3 = 0; i3 < 1000; i3++)
{
long id = (long)ids[rnd.Next(19999)];
var t = session.Get<SimpleObject>(id);
var no = t.StringProperty;
}
Interlocked.Add(ref ops, 1000);
tx.Commit();
}
}
结果
使用的版本
这些提供程序与SysCache2实现之间的性能是否有所不同?
正如Frederic指出的那样,测试场景并没有太多意义,因为比较了两种不同类别的具有两种不同用例的缓存架构。第一类(5&amp; 6)不能水平缩放,而1和2可以。目前,SQL-Server在同一台机器上运行,因此使用共享内存作为IPC机制,因此我禁用了所有IPC连接可能性,并将其配置为使用TCP / IP连接到数据库。结果,no-cache-scenario的性能下降了大约10000 op / s,这使得最快的分布式缓存提供程序进入合理的距离。
通过比较缓存提供程序,我想测试这些提供程序是否可用于每个请求的会话设置,以缓存国家,货币或资产负债表结构等参考数据。由于性能最佳的分布式缓存的性能仍然只是普通NHibernate版本运行的一半,我不确定这是否可行。
答案 0 :(得分:1)
让SysCache(2)
(或RtMemoryCache
如果你也尝试另一个)表现得比Redis
或MemCached
高得多也就不足为奇了。前者是进程内存缓存,它们的使用不会产生任何网络IO,也不会产生任何进程间通信。这些缓存是分布式缓存,它们至少意味着进程间通信,在大多数情况下意味着网络IO,这会导致相当高的使用成本。
将分布式缓存性能与非分布式缓存性能进行比较并没有任何意义。只有在需要在多个进程之间共享缓存时,才应使用分布式缓存。如果您有此要求,则无法使用非分布式缓存。
令人惊讶的是让“无缓存”方案(因此,SQL查询)比分布式缓存执行得更好。
在我看来,测试描述中缺少一个关键点:在您的场景中,SQL查询的性能成本是什么?如果数据库服务器托管在与Web服务器相同的物理主机上,则与通常的设置相比,此成本相当低。像SQL服务器这样的数据库解决方案甚至可以跳过任何网络IO,并且当它们托管在与Web服务器相同的主机上时,通过命名管道进行内部通信的进程间。
附注:如果您不考虑将SysCache2
配置为通过SQL Server数据更改通知获取无效,则应该测试SysCache
,而不是更轻。 (但这可能不会真正改变您的测试场景中的结果。)
首先要确保您确实需要分发缓存。在以下情况下,每个进程都可以安全地拥有自己的缓存:
当然,对于非分布式缓存,数据缓存预热会更慢,但如果分布式缓存执行得太差,那么这不是重点。
如果您需要分发它,那么您应该评估您的SQL Server是否是负载下的瓶颈。如果负载不足,您的SQL Server可能成为应用程序的瓶颈,那么分布式缓存将有助于卸载它。否则,最好不要使用它们,如果在您的设置中,分布式缓存的性能始终比数据库服务器差。
附注:如果只满足条件(2.),您还可以尝试使用SQL Server通知失效的非分布式缓存,以避免过时的数据。请参阅此处以获取how to configure SysCache2
以获得SQL Server的通知。
答案 1 :(得分:1)
弗雷德里克已经写过你测试了两种完全不同类型的缓存,所以我不打算再重复一遍。但我会添加一些有关NH缓存如何工作的信息并回答Frederic的评论:
令人惊讶的是,没有缓存&#34;场景(所以,SQL 查询)比分布式缓存执行得更好。
实际上,没有任何意外:)你需要记住:
另外,我必须说你的测试不是很有代表性。在运行这些性能测试之前,您需要
当然,对数据进行测试而不是对虚拟数据集进行测试;)