关于Memcache mutex设计模式的.net实现
原文链接:http://timyang.net/programming/memcache-mutex/
为了实现原文中的对象到期时间属性,定义了一个基类,其信息如下:

public class CacheObj
{
/// <summary>
/// 数据绝对到期时间,默认为当前时间开始三分钟后失效
/// </summary>
public DateTime ExpireTime = DateTime.Now.AddMinutes(3);
/// <summary>
/// 数据相对有效时间,单位:秒。默认为30秒有效期
/// </summary>
public int TimeOut = 30;
}
这样所有要放到memcached的对象只要继承该对象就OK了,比如下面的用户信息类:

/// 用户信息
/// </summary>
[Serializable]
public class UserInfo : CacheObj
{
public string UserName;
public int Age;
public string Email;
public override string ToString()
{
return "UserName:" + UserName + " Age:" + Age + " Email:" + Email;
}
}
下面是原文中方式一的实现代码:

//方一
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 = "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数据
}
}
return value;
}
下面是方式2的代码:

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;
}
源码下载地址:/Files/daizhj/MemcachedApp.rar
【示例位于MemcachedApp\sample\MutexSample.aspx】
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
2015-06-01 CSS clip:rect矩形剪裁功能及一些应用介绍