NHibernate二级缓存性能

时间:2016-03-31 14:52:08

标签: nhibernate nhibernate-caches

在研究nhibernate中二级缓存提供的可能性时,我测试了一些实现。目前结果非常出乎意料,我怀疑我的期望是否错误。

  1. 场景(Read-Heavy)
  2. 首先将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();
        }
    }
    

    结果

    1. Redis 5000每秒读取次数
    2. MemCached 8000每秒读取次数(EnyimMemcached)
    3. 每秒不缓存15000次读取(同一台机器,TCP-IP)
    4. 没有缓存每秒25000次读取(相同的机器,共享内存)
    5. SysCache2每秒200000次读取
    6. HashtableCacheProvider每秒380000次读取
    7. 使用的版本

      这些提供程序与SysCache2实现之间的性能是否有所不同?

      更新1

      正如Frederic指出的那样,测试场景并没有太多意义,因为比较了两种不同类别的具有两种不同用例的缓存架构。第一类(5&amp; 6)不能水平缩放,而1和2可以。目前,SQL-Server在同一台机器上运行,因此使用共享内存作为IPC机制,因此我禁用了所有IPC连接可能性,并将其配置为使用TCP / IP连接到数据库。结果,no-cache-scenario的性能下降了大约10000 op / s,这使得最快的分布式缓存提供程序进入合理的距离。

      通过比较缓存提供程序,我想测试这些提供程序是否可用于每个请求的会话设置,以缓存国家,货币或资产负债表结构等参考数据。由于性能最佳的分布式缓存的性能仍然只是普通NHibernate版本运行的一半,我不确定这是否可行。

2 个答案:

答案 0 :(得分:1)

SysCache(2)(或RtMemoryCache如果你也尝试另一个)表现得比RedisMemCached高得多也就不足为奇了。前者是进程内存缓存,它们的使用不会产生任何网络IO,也不会产生任何进程间通信。这些缓存是分布式缓存,它们至少意味着进程间通信,在大多数情况下意味着网络IO,这会导致相当高的使用成本。

将分布式缓存性能与非分布式缓存性能进行比较并没有任何意义。只有在需要在多个进程之间共享缓存时,才应使用分布式缓存。如果您有此要求,则无法使用非分布式缓存。

令人惊讶的是让“无缓存”方案(因此,SQL查询)比分布式缓存执行得更好。

在我看来,测试描述中缺少一个关键点:在您的场景中,SQL查询的性能成本是什么?如果数据库服务器托管在与Web服务器相同的物理主机上,则与通常的设置相比,此成本相当低。像SQL服务器这样的数据库解决方案甚至可以跳过任何网络IO,并且当它们托管在与Web服务器相同的主机上时,通过命名管道进行内部通信的进程间。

附注:如果您不考虑将SysCache2配置为通过SQL Server数据更改通知获取无效,则应该测试SysCache,而不是更轻。 (但这可能不会真正改变您的测试场景中的结果。)

寻址更新1:

首先要确保您确实需要分发缓存。在以下情况下,每个进程都可以安全地拥有自己的缓存:

  1. 缓存数据是只读的(或者最终,如果某些进程提供过时的缓存数据不会导致应用程序出现问题)。
  2. 这不会导致大量内存消耗。 (缓存数据并不重,在许多进程中复制它不会成为问题。)
  3. 当然,对于非分布式缓存,数据缓存预热会更慢,但如果分布式缓存执行得太差,那么这不是重点。

    如果您需要分发它,那么您应该评估您的SQL Server是否是负载下的瓶颈。如果负载不足,您的SQL Server可能成为应用程序的瓶颈,那么分布式缓存将有助于卸载它。否则,最好不要使用它们,如果在您的设置中,分布式缓存的性能始终比数据库服务器差。

    附注:如果只满足条件(2.),您还可以尝试使用SQL Server通知失效的非分布式缓存,以避免过时的数据。请参阅此处以获取how to configure SysCache2以获得SQL Server的通知。

答案 1 :(得分:1)

弗雷德里克已经写过你测试了两种完全不同类型的缓存,所以我不打算再重复一遍。但我会添加一些有关NH缓存如何工作的信息并回答Frederic的评论:

  

令人惊讶的是,没有缓存&#34;场景(所以,SQL   查询)比分布式缓存执行得更好。

实际上,没有任何意外:)你需要记住:

  1. NHibernate尝试使用缓存来保证安全并模拟&#34;事务&#34;在每个缓存的实体上。根据其实现,分布式(NHibernate)缓存可以向缓存服务器(锁定和释放实体)发送两个额外的请求,导致严重的性能下降
  2. 不同的缓存使用不同的序列化程序。例如,Redis缓存使用内置的.NET XML序列化程序,它的速度并不出名;)
  3. 根据配置的过期策略,如果使用分布式缓存,则可能还会有额外的性能下降
  4. 一些缓存服务器(如Redis)可能会因为资源压力导致缓存条目被删除而导致严重的性能问题(在这种情况下,NH将进入缓存服务器,获取缓存未命中,然后尝试从数据库中检索实体=&gt; 2x网络电话)
  5. 另外,我必须说你的测试不是很有代表性。在运行这些性能测试之前,您需要

    • 检查将在缓存中存储多少实体
    • 多少&#34; put&#34;与&#34;得到&#34;你有这些实体
    • 您在缓存实体中拥有多少个链接集合
    • 平均在关联馆藏中存储了多少项目
    • 你有什么样的实体(readonly,主要是不可变的或者所有实体都可以更新?)

    当然,对数据进行测试而不是对虚拟数据集进行测试;)