Question

I have my website code on two servers and I want a shared cache between them, so I am using Microsoft AppFabric. I only ever want there to be one item in the cache -- not one item per site visitor, just one item total.

The code I'm using to try to accomplish this is below, however, it is not working the way I want it to. I think the problem is that there are many items in the cache, despite them all having the same key. But it could be something else that's happening. See the code comments for more details.

In Web.config:

<dataCacheClient>
    <hosts>
      <host name="MyHost1" cachePort="22233"/>
      <host name="MyHost2" cachePort="22233"/>
    </hosts>
    <securityProperties mode="None" protectionLevel="None" />
</dataCacheClient>
...
<system.web>
    <sessionState mode="InProc" customProvider="AppFabricCacheSessionStoreProvider">
        <providers>
            <add
                name="AppFabricCacheSessionStoreProvider"
                type="Microsoft.ApplicationServer.Caching.DataCacheSessionStoreProvider"
                cacheName="MyCache"
                sharedId="MySharedApp"/>
        </providers>
    </sessionState>
    ...
</system.web>

In Global.asax.cs:

private static DataCacheFactory _cacheFactory = new DataCacheFactory();
private static DataCache _cache;

private void RegisterCacheEntry(){
    try
    {
        // Set up cache
        _cache = _cacheFactory.GetCache("MyCache");

        // Prevent duplicate key addition
        if (_cache.GetCacheItem(CacheItemKey) != null || _cache.Get(CacheItemKey) != null) 
            return;

        // Add item to cache
        _cache.Add(CacheItemKey, CacheItem, TimeSpan.FromMinutes(10));

        // When the cache item is removed, the callback:
        // 1) sends me an email 
        // 2) adds the same item with the same key to the cache again.
        // So I SHOULD be getting one email every 10 minutes.
        // However, it starts with one, but the number of emails that I get increases every 10 minutes.
        // i.e., I get one email at time t=0, two emails at t=1, three at t=2, then four, etc.
        _cache.AddItemLevelCallback(CacheItemKey, DataCacheOperations.RemoveItem, CacheItemRemovedCallback);
    }
    catch (Exception e){}
}

If you want more information on what I'm doing and why, I'm trying to simulate a Windows Service using cache timeout as described here. But I'm trying to get this to work on two servers.

Was it helpful?

Solution

You added AppFabric Session State Provider in web.config. All sessions will be persisted in the cluster : that's why you have multiple cache items.

Also, you will need to add an extra error management in your system, as said here :

Cache hosts can hold only a certain amount of cache operations in memory. It is possible, depending on system load, that some cache clients may not receive notifications before they are truncated in the cache host queues. Cache clients may also miss notifications when data is lost due to a cache server failure while the rest of the cluster remains running. In these cases, your cache client can discover that it has missed some cache notifications by using a failure notification. Your application can add a callback to receive failure notifications by using the AddFailureNotificationCallback method. For more information, see Add a Failure Notification Callback

EDIT : CacheItemRemovedCallback provides the key that is removed from the cache. Check if it's the always the same.I also recommand to not limit the distributed cached to a single item : if someone else add something in the cache your system will fails.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top