//方法二
public UserInfo GetCacheData2(string key)
{
UserInfo value = mc.Get(key) as UserInfo;
if (value == null)
{
// 3 分钟到期,在delete之前,当前key_mutex add只能被添加一次并返回true
if (mc.Add(key + "_mutex", "add_mutex", DateTime.Now.AddMinutes(3)) == true)
{
value = new UserInfo() { UserName = "daizhj", Email = "daizhj617595@126.com" };// 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数据
}
}
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 = "617595@163.com" };// db.get(key);
value.ExpireTime = DateTime.Now.AddSeconds(value.TimeOut);
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数据
}
}
}
return value;
}