缓存锁
问题:
如果一个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);
}
}
}
}
浙公网安备 33010602011771号