加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

使用Windows Server AppFabric缓存的分布式锁服务

发布时间:2020-12-14 02:51:38 所属栏目:Windows 来源:网络整理
导读:我有一个在 Windows Server AppFabric SDK中找到的Microsoft.ApplicationServer.Caching.DataCache对象的扩展方法,如下所示: using System;using System.Collections.Generic;using Microsoft.ApplicationServer.Caching;namespace Caching{ public static
我有一个在 Windows Server AppFabric SDK中找到的Microsoft.ApplicationServer.Caching.DataCache对象的扩展方法,如下所示:

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,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());

执行潜在长时间运行的函数的锁定限制调用单个线程,但仅限于同一台机器上的单个进程.您将如何扩展此模式以使锁定分布以防止多个进程/机器立即执行该函数?

解决方法

AppFabric拥有自己的分布式锁定机制,您可以通过GetAndLock / PutAndUnlock方法系列访问它.如果您的项目被锁定,正常的Get调用仍将成功并返回最后一个值,但进一步的GetAndLock调用将抛出异常.在您的客户端第一次请求缓存对象的情况下,您仍然可以锁定密钥,即使它尚不存在(它更像是一个预留而不是一个实体锁).

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

    if (result == null)
    (
        DataCacheLockHandle handle;
        // We need a timespan to allow func time to run
        TimeSpan funcTimespan = New TimeSpan(0,1,0);

        try
        {
            // Lock the key
            // If something goes wrong here it will unlock at the end of funcTimespan
            var result = @this.GetAndLock(key,funcTimespan,handle);

            if (result == null)
            {
                // Still no value so go and run func
                result = func();

                @this.PutAndUnlock(key,handle,timeout);
            }
            else
            {
                // There's a value now so we'll unlock the key and reset it's timeout
                @this.Unlock(key,timeout);
            }
        }
        catch (DataCacheException ex)
        {
            if (ex.ErrorCode == DataCacheErrorCode.ObjectLocked)
            {
                // Another process has locked the key so func must be running right now
                // We'll return null to the client
                result = null;
            }
        }

        if (result == null)
        {
            return null;
        }
        else
        {
            return (T)result;
        }
    )
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读