天天看點

關于Memcache mutex設計模式的.net實作

之前在網上看過memcache-mutex的場景分析和實作代碼,這裡将.net方式加以實作,當然這裡主要是依據原文的僞代碼照貓畫虎,以此做為總結及記錄。如果您對相應實作感興趣可以嘗試使用本文提供的代碼進行測試,如果有問題請及時與我聯系。   

     為了實作原文中的對象到期時間屬性,定義了一個基類,其資訊如下:

關于Memcache mutex設計模式的.net實作
關于Memcache mutex設計模式的.net實作

[Serializable]

public class CacheObj

{

        /// <summary>

        /// 資料絕對到期時間,預設為目前時間開始三分鐘後失效

        /// </summary>

        public DateTime ExpireTime = DateTime.Now.AddMinutes(3);      

        /// 資料相對有效時間,機關:秒。預設為30秒有效期

        public int TimeOut = 30;

}

關于Memcache mutex設計模式的.net實作

     這樣所有要放到memcached的對象隻要繼承該對象就OK了,比如下面的使用者資訊類: 

關于Memcache mutex設計模式的.net實作
關于Memcache mutex設計模式的.net實作

/// <summary>

/// 使用者資訊

/// </summary>

public class UserInfo : CacheObj

        public string UserName;

        public int Age;

        public string Email;

        public override string ToString()

        {

            return "UserName:" + UserName + "  Age:" + Age + "  Email:" + Email;

        }

關于Memcache mutex設計模式的.net實作

     下面是原文中方式一的實作代碼:

關于Memcache mutex設計模式的.net實作
關于Memcache mutex設計模式的.net實作

MemcachedClient mc = MemCachedManager.CacheClient;

//方一

public UserInfo GetCacheData1(string key)

    UserInfo value = mc.Get(key) as UserInfo;

    if (value == null)

    {

        // 3 分鐘到期.在delete操作執行之前,目前key_mutex add隻能被添加一次并傳回true

        if (mc.Add(key + "_mutex", key + "_mutex", DateTime.Now.AddMinutes(3)) == true)

            value = new UserInfo() { UserName = "daizhj", Email = "[email protected]" };// db.get(key);//從加載資料

            mc.Set(key, value);

            mc.Delete(key + "_mutex");                    

        else

            System.Threading.Thread.Sleep(500);//如果設定過短,可能上面set文法還未生效

            value = mc.Get(key) as UserInfo;//sleep之後重試讀取cache資料

    }

    return value;

關于Memcache mutex設計模式的.net實作

    下面是方式2的代碼:

關于Memcache mutex設計模式的.net實作
關于Memcache mutex設計模式的.net實作

//方法二

public UserInfo GetCacheData2(string key)

        // 3 分鐘到期,在delete之前,目前key_mutex add隻能被添加一次并傳回true

        if (mc.Add(key + "_mutex", "add_mutex", DateTime.Now.AddMinutes(3)) == true)

            mc.Delete(key + "_mutex");

    else

        if (value.ExpireTime <= DateTime.Now)

            //有值但已過期 

            if (mc.Add(key + "_mutex", "add_mutex", DateTime.Now.AddMinutes(3)) == true)

            {

                value.ExpireTime = DateTime.Now.AddSeconds(value.TimeOut);

                //這隻是為了讓它先暫時有效(後面即将更新該過期資料),這樣做主要防止避免cache失效時刻大量請求擷取不到mutex并進行sleep,注意這裡設定成有效會導緻其它線程會暫時讀到髒資料

                mc.Set(key, value, DateTime.Now.AddSeconds(value.TimeOut * 2));//這裡*2是為了讓memcached緩存資料更長時間,因為真正校驗到期時間用ExpireTime來判斷

                //從資料源加載最新資料

                value = new UserInfo() { UserName = "daizhenjun", Email = "[email protected]" };// db.get(key);

                mc.Set(key, value, DateTime.Now.AddSeconds(value.TimeOut * 2));

                mc.Delete(key + "_mutex");

            }

            else

                System.Threading.Thread.Sleep(500);//如果設定過短,可能上面set文法還未生效

                value = mc.Get(key) as UserInfo;//sleep之後重試讀取cache資料

關于Memcache mutex設計模式的.net實作

      無論使用那種方式,都會帶來代碼複雜性增大(尤其第二種),另外還有就是與memcached額外的連接配接及存儲開銷(key_mutex本身存儲也要消耗資源)。因為除非是高并發場景下同時更新memcached,否則這兩種方式需要斟酌使用。