33

我正在寻找最高效的方式来安排 AppFabric 缓存调用的数据缓存和数据缓存工厂的使用,每页加载 400 到 700 个缓存获取(几乎没有任何放置)。似乎使用单个静态 DataCacheFactory (或者可能是循环设置中的一对)是要走的路。

我是为每个 DataCache 对象请求调用 GetCache("cacheName"),还是在初始化 DataCache 工厂时将其设为静态并将其用于所有调用?

我是否必须处理异常、检查失败代码并尝试重试?

当多个线程尝试使用缓存存储并想要相同的项目(按键)时,我是否必须考虑争用?

是否有某种文档可以正确探索其设计和使用?


到目前为止我从论坛收集的一些信息:

http://social.msdn.microsoft.com/Forums/en-AU/velocity/thread/98d4f00d-3a1b-4d7c-88ba-384d3d5da915

“创建工厂涉及连接到集群,可能需要一些时间。但是一旦你有了工厂对象和想要使用的缓存,你就可以简单地重用这些对象来执行放入和进入缓存,你应该看到更快的性能。”

http://social.msdn.microsoft.com/Forums/en-US/velocity/thread/0c1d7ce2-4c1b-4c63-b525-5d8f98bb8a49

“创建单个 DataCacheFactory(单例)比创建多个 DataCacheFactory 性能更高。您不应该为每个调用创建 DataCacheFactory,它会影响性能。”

“请尝试在您的单例中封装循环算法(具有 3/4/5 个工厂实例)并比较负载测试结果。”

http://blogs.msdn.com/b/velocity/archive/2009/04/15/pushing-client-performance.aspx

“您可以增加客户端的数量以增加缓存吞吐量。但有时如果您希望拥有较小的客户端集并增加吞吐量,一个技巧是使用多个 DataCacheFactory 实例。DataCacheFactory 实例创建与服务器的连接(例如.g 如果有 3 个服务器,它将创建 3 个连接)并将来自数据缓存的所有请求多路复用到这些连接。因此,如果 put/get 量非常高,这些 TCP 连接可能会成为瓶颈。所以一种方法是创建多个 DataCacheFactory 实例,然后对它们使用操作。”


到目前为止,这里正在使用什么......该属性被调用,如果返回值不为空,则执行操作。

private static DataCache Cache
{
    get
    {
        if (_cacheFactory == null)
        {
            lock (Sync)
            {
                if (_cacheFactory == null)
                {
                    try
                    {
                        _cacheFactory = new DataCacheFactory();
                    }
                    catch (DataCacheException ex)
                    {
                        if (_logger != null)
                        {
                            _logger.LogError(ex.Message, ex);
                        }
                    }
                }
            }
        }

        DataCache cache = null;

        if (_cacheFactory != null)
        {
            cache = _cacheFactory.GetCache(_cacheName);
        }

        return cache;
    }
}

在 Microsoft AppFabric 论坛上查看此问题:http: //social.msdn.microsoft.com/Forums/en-AU/velocity/thread/e0a0c6fb-df4e-499f-a023-ba16afb6614f

4

2 回答 2

16

以下是论坛帖子的答案:

你好。抱歉延迟回复,但我想说这些都是很好的问题,可能对其他人有用。

除非您需要不同的配置,否则每个线程不需要多个 DataCacheFactory。例如,如果您使用 DataCacheFactoryConfiguration 类以编程方式配置 DataCacheFactory,那么您可能希望创建一个启用本地缓存而另一个不启用的。在这种情况下,您将根据场景所需的配置使用不同的 DataCacheFactory 对象。但是除了配置上的差异之外,您不应该看到通过创建多个 DataCacheFactories 来获得性能提升。

在同一主题上,有一个 MaxConnectionsToServer 设置(在 DataCacheFactoryConfiguration 中或在应用程序配置文件中作为 dataCacheClient 元素的属性编程)。这决定了向缓存集群打开的每个 DataCacheFactory 的通道数。如果您有高吞吐量要求并且还有可用的 CPU/网络带宽,则将此设置增加到 3 或更高可以增加吞吐量。我们不建议无缘无故地增加此值或将其值增加到无法满足您的需要的值。您应该更改该值,然后测试您的方案以观察结果。我们希望将来有更多的官方指导。

一旦有了 DataCacheFactory,就不需要多次调用 GetCache() 来获取多个 DataCache 对象。对同一工厂上的同一缓存的每次调用 GetCache() 都会返回相同的 DataCache 对象。此外,一旦有了 DataCache 对象,就不需要继续为它调用 DataCacheFactory。只需存储 DataCache 对象并继续使用它。但是,不要让 DataCacheFactory 对象被释放。DataCache 对象的生命周期与 DataCacheFactory 对象相关联。

您永远不必担心与 Get 请求的争用。但是,对于 Put/Add 请求,如果多个数据缓存客户端同时更新同一个键,则可能会发生争用。在这种情况下,您将收到错误代码为 ERRCA0017、RetryLater 和子状态为 ES0005、KeyLatched 的异常。但是,您可以轻松添加异常处理和重试逻辑,以便在发生此类错误时再次尝试更新。这可以为具有各种子状态值的 RetryLater 代码完成。有关详细信息,请参阅 http://msdn.microsoft.com/en-us/library/ff637738.aspx. 您还可以通过使用 GetAndLock() 和 PutAndUnlock() API 来使用悲观锁定。如果您使用此方法,您有责任确保所有缓存客户端都使用悲观锁定。Put() 调用将清除先前由 GetAndLock() 锁定的对象。

我希望这有帮助。就像我说的,我们希望尽快将这种类型的指导纳入一些正式的内容。但在那之前最好在论坛上分享它。谢谢!

杰森·罗斯

于 2010-12-02T05:05:38.257 回答
4

我是为每个 DataCache 对象请求调用 GetCache("cacheName"),还是在初始化 DataCache 工厂时将其设为静态并将其用于所有调用?

我想答案应该是;GetCache尝试两种方式,看看是否有区别,但在我看来,一个静态 DataCache 比每次调用 Get 时对应的调用更有意义。

那篇“推动客户端性能”的文章表明,有一个最佳点,即 DataCacheFactory 实例的数量可以让您获得最大性能,超出内存开销开始对您不利 - 遗憾的是他们没有给出任何指导方针(甚至是经验法则) 这个地点可能在哪里。

我还没有遇到任何关于最大化性能的文档——我认为 AppFabric 仍然太新,以至于这些指南还没有被淘汰。我确实看过Pro AppFabric 书的 Contents ,但它似乎更关注 AppFabric 的工作流(都柏林)方面,而不是缓存(速度)部分。

不过我要说的一件事是:您是否有可能缓存“更粗”的对象,这样您就可以减少对 的调用Get?您可以缓存集合而不是单个对象,然后在客户端解压缩集合吗?每页加载 700 次缓存在我看来是一个巨大的数字!

于 2010-09-24T15:08:09.070 回答