博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于Memcache mutex设计模式的.net实现
阅读量:5999 次
发布时间:2019-06-20

本文共 2992 字,大约阅读时间需要 9 分钟。

     之前在网上看过memcache-mutex的场景分析和实现代码,这里将.net方式加以实现,当然这里主要是依据原文的伪代码照猫画虎,以此做为总结及记录。如果您对相应实现感兴趣可以尝试使用本文提供的代码进行测试,如果有问题请及时与我联系。   

     原文链接:http://timyang.net/programming/memcache-mutex/

     本地链接:http://www.cnblogs.com/daizhj/articles/1959704.html

 

     为了实现原文中的对象到期时间属性,定义了一个基类,其信息如下:

 

ExpandedBlockStart.gif
[Serializable]
public
 
class
 CacheObj
{
        
///
 
<summary>
        
///
 数据绝对到期时间,默认为当前时间开始三分钟后失效
        
///
 
</summary>
        
public
 DateTime ExpireTime 
=
 DateTime.Now.AddMinutes(
3
);      
        
///
 
<summary>
        
///
 数据相对有效时间,单位:秒。默认为30秒有效期
        
///
 
</summary>
        
public
 
int
 TimeOut 
=
 
30
;
}

     这样所有要放到memcached的对象只要继承该对象就OK了,比如下面的用户信息类:

ExpandedBlockStart.gif
///
 
<summary>
///
 用户信息
///
 
</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;
        }
}

     下面是原文中方式一的实现代码:

 

ExpandedBlockStart.gif
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 
=
 
"
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的代码:

 

ExpandedBlockStart.gif
//
方法二
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;
}

     
无论使用那种方式,都会带来代码复杂性增大(尤其第二种),另外还有就是与memcached额外的连接及存储开销(key
_mutex本身存储也要消耗资源
)。因为除非是高并发场景下同时更新memcached,否则这两种方式需要斟酌使用。

 

      源码下载地址:  

      【示例位于MemcachedApp\sample\MutexSample.aspx】

 

你可能感兴趣的文章
Ajax在java前台中怎么运用
查看>>
邮件加密网关之隐密邮介绍
查看>>
云计算开发和大数据的概念和关系,云计算开发怎么学?
查看>>
PXE服务器
查看>>
Spark SQL 报错总结
查看>>
DOS命令安装系统服务
查看>>
Oracle技术之SYS用户对象不支持延迟段
查看>>
Linux下升级 OpenSSH
查看>>
git操作详解
查看>>
JAVA枚举(一)引入枚举知识点的前戏
查看>>
java多线程编程之简介
查看>>
关于已经上线项目的升级的启示
查看>>
jquery 纯js右下角弹窗
查看>>
标准功能模块组件 -- 名片管理组件,C\S 版本的标准用例程序,可以参考权限实现方法...
查看>>
看看一个朋友写的代码,大家发表发表意见,比较简单的代码
查看>>
CentOS 6.0下vncserver安装配置
查看>>
ZooKeeper-3.4.6学习笔记汇总
查看>>
Apache Shiro学习笔记(二)身份验证subject.login过程
查看>>
我的友情链接
查看>>
Linux查看CPU和内存使用情况
查看>>