缓存锁

问题:

如果一个sql要执行很久,同时有两个人先后访问,则该sql被执行两次。如果有中间表,可能造成重复插入等问题。

 

解决方法:

using Senparc.CO2NET.Cache;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace test.Controllers
{
    public class OpenController : BaseController
    {
        static LocalObjectCacheStrategy cache = (LocalObjectCacheStrategy)CacheStrategyFactory.GetObjectCacheStrategyInstance();
        static int cacheMinutes = 600;

        public JsonResult Index(string name, string ps)
        {
            try
            {
                string data = null;
                switch (name)
                {
                    case "g$bi_auth":
                        data = ExecuteProcToJson(name, ps);
                        break;
                    case "r$ncc_tracking":
                        data = ExecuteProcToJson(name, ps);
                        break;
                    case "r$ncc_tracking_kpi":
                        data = ExecuteProcToJson(name, ps);
                        break;
                    case "r$ec_tracking_by_channel":
                        data = ExecuteProcToJson(name, ps);
                        break;
                    case "r$ec_tracking_ttl":
                        data = ExecuteProcToJson(name, ps);
                        break;
                    case "r$social_tracking_forward":
                        data = ExecuteProcToJson(name, ps);
                        break;
                    default:
                        data = getCache(name, ps, cacheMinutes);
                        break;
                }
                if (data != null)
                    return Json(new { code = "0", message = "OK", data = data }, JsonRequestBehavior.AllowGet);
                else
                    return Json(new { code = "-1", message = name + "接口不存在" }, JsonRequestBehavior.AllowGet);
            }
            catch (Exception ex)
            {
                return Json(new { code = "-1", message = ex.Message }, JsonRequestBehavior.AllowGet);
            }
        }

        public JsonResult Clear()
        {
            Hashtable cs = new Hashtable();
            foreach (var ca in cache.GetAll())
            {
                cs.Add(ca.Key, ca.Key);
            }
            foreach (DictionaryEntry c in cs)
            {
                cache.RemoveFromCache(c.Key.ToString(), true);
            }
            return Json(new { code = "0", message = "OK" }, JsonRequestBehavior.AllowGet);
        }

        public string getCache(string proc, string ps, int min)
        {
            string data = null;
            //如果已经有结果,直接返回数据
            if (cache.CheckExisted(proc + "-" + ps) &&
                DateTime.Now.Subtract((DateTime)((object[])cache.Get(proc + "-" + ps))[0]).Minutes < min&& ((object[])cache.Get(proc + "-" + ps))[2].ToString()=="1")
                data = ((object[])cache.Get(proc + "-" + ps))[1].ToString();       
            //如果第一次执行
            else
            {   //设置缓存
                if (!cache.CheckExisted(proc + "-" + ps))
                    cache.Set(proc + "-" + ps, new object[]
                   {
                    DateTime.Now,
                    data,
                    0
                   });
                //锁定缓存
                using (var checkLock=cache.BeginCacheLock("proc", proc + "-" + ps))
                {   //如果多线程访问,第一个已经执行完成,则重新判断缓存是否完成
                    if (cache.CheckExisted(proc + "-" + ps) &&
            DateTime.Now.Subtract((DateTime)((object[])cache.Get(proc + "-" + ps))[0]).Minutes < min && ((object[])cache.Get(proc + "-" + ps))[2].ToString() == "1")
                    {
                        data = ((object[])cache.Get(proc + "-" + ps))[1].ToString();
                        checkLock.UnLock("proc");
                        return data;
                    }
                    //第一次执行
                    else if (checkLock.LockSuccessful)
                    {
                        data = ExecuteProcToJson(proc, ps);
                        cache.Update(proc + "-" + ps, new object[]
                    {
                    DateTime.Now,
                    data,
                    1
                    });
                        checkLock.UnLock("proc");
                    }
                }


                }
            return data;
        }

        public void removeCache(string proc)
        {
            Hashtable cs = new Hashtable();
            foreach (var ca in cache.GetAll())
            {
                cs.Add(ca.Key, ca.Key);
            }
            foreach (DictionaryEntry c in cs)
            {
                if (c.Key.ToString().IndexOf(proc + "-") >= 0)
                    cache.RemoveFromCache(c.Key.ToString(), true);
            }
        }

    }
}

 

posted @ 2018-08-23 17:41  KJXY  阅读(216)  评论(0)    收藏  举报