关于memcache实现Mutex模式的解析

实施对象:memcache
设计理论:mutex
设计前提:大量并发访问并存在cache过期。大并发场合,当cache失效导致同时取不到cache,会同一时间访问db并回设cache,可能会给系统带来潜在的超负荷风险。
 
解决方案:
方案一:load db之前add一个mutex key ,mutex key add 成功再去取db; add 失败则sleep之后重读cache。这里mutex key其实就是锁,因为memcache是没有锁概念,加了锁就能保证一个进程去操作对一个数据对象的db取操作,从而降低了风险。但是为了防止出现死锁现象,mutex是有时间限制。伪代码如下:
If(memcache.get(key)==null){ 
   If(memcache.add(mutex_key,1,mutex_timeout)===TRUE){ 
 
v=db.get(key);
memcache.set(key,v,timeout);
            memcache.delete(mutex_key);
}else{
      Sleep(50);
      Retry(); 
}
 
}
 
解析: mutex设计理论其实就是一个防止并发访问,从而用强加锁的机制,先抢到锁的线程就直接进行数据处理“db.get-> memcache.set” ,其余,就根据mutex_key的状态进行等待。两个时间点很重要:一是mutex_key的时间,你需要评估数据从db获取然后重设到cache周期。比如3分钟,在3分钟内,任何memcahce.add操作都会失败,根据memcache的add的API定义,当前key存在add就会失败,从而实现了锁的概念,一旦存在就是加锁状态。
第二个时间点是,sleep时间,相对来说,这个时间是线程等待然后重新请求的时间,休眠状态不宜过长。
 
 
方案二:相对方案一,将cache做了一个辅助作用,它不在于memcache.get有value的时候,假设我们需要的cache数据的时间为timeout,那么我们同时设置一个timeout1为内部超时时间,其中,timeout1<timeout,当cache接近或是已经超时,我们延长cache时间TIME_OUT,目的是维持cache状态,同时启用新的任务从db读取数据并回设cache。
If(memcache.get(key)==null){
    // 同方案一一样,这里就不代码补充
}else{
  If(v.timeout<=now()){
      If(memcache.add(mutex_key,1,mutex_timeout)===TRUE){
      v.timeout+=3*60*1000; //单位是毫秒
      memcache.set(key,v,KEY_TIMEOUT*2);
// 重新任务进行cache回设
     v=db.get(key);
       v.timeout=KEY_TIMEOUT;
     memcache.set(key,v,TIME_OUT*2); //新cache替代原先的cache
     memcache.delete(mutex_key);
}else{
       Sleep(50);
  Retry();
 
}
}
 
}
 
解析:方案二是在一的基础上,在cache尚未过期可以取到值的时候做了一个优化,就是评估时间接近过期前,延长cache过期时间,为的是在db数据回设cache的时间内,cache的连续性,在新数据载入缓存期间,原有缓存依然担任读取的重要责任。
 
 
相比之下,方案二在实施过程中将伪代码转向实际代码实现复杂度会提升很多,一般场合来说方案一代码足够,如果实在需要考虑在缓存过期前做一些cache提前更新,那么需要考虑设置一个内定时间限制,一旦超过这个时间限定就开

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值