Служба распределенной блокировки с кэшированием Windows Server AppFabric

У меня есть метод расширения для объекта Microsoft.ApplicationServer.Caching.DataCache, найденный в Windows Server AppFabric SDK, который выглядит следующим образом:

using System;
using System.Collections.Generic;
using Microsoft.ApplicationServer.Caching;

namespace Caching
{
    public static class CacheExtensions
    {
        private static Dictionary<string, object> locks = new Dictionary<string, object>();

        public static T Fetch<T>(this DataCache @this, string key, Func<T> func)
        {
            return @this.Fetch(key, func, TimeSpan.FromSeconds(30));
        }

        public static T Fetch<T>(this DataCache @this, string key, Func<T> func, TimeSpan timeout)
        {
            var result = @this.Get(key);

            if (result == null)
            {
                lock (GetLock(key))
                {
                    result = @this.Get(key);

                    if (result == null)
                    {
                        result = func();

                        if (result != null)
                        {
                            @this.Put(key, result, timeout);
                        }
                    }
                }
            }

            return (T)result;
        }

        private static object GetLock(string key)
        {
            object @lock = null;

            if (!locks.TryGetValue(key, out @lock))
            {
                lock (locks)
                {
                    if (!locks.TryGetValue(key, out @lock))
                    {
                        @lock = new object();
                        locks.Add(key, @lock);
                    }
                }
            }

            return @lock;
        }
    }
}

Цель состоит в том, чтобы позволить разработчику написать код, который говорит: "выборка мне некоторые данные, сначала попробовав кеш. если он недоступен в кеше, выполните указанную функцию, поместите результаты в кеш для следующего вызывающего абонента, а затем верните результаты ". Примерно так:

var data = dataCache.Fetch("key", () => SomeLongRunningOperation());

Блокировка ограничивает выполнение потенциально длительного вызова функции одним потоком, но только в рамках одного процесса на той же машине. Как бы вы расширили этот шаблон, чтобы сделать блокировку распределенной, чтобы предотвратить одновременное выполнение функции несколькими процессами / машинами?

5
задан Shawn Miller 23 February 2011 в 16:51
поделиться