当前位置:首页 > PHP教程 > php高级应用 > 列表

PHP使用Memcache时模拟命名空间及缓存失效问题的解决

发布:smiling 来源: PHP粉丝网  添加日期:2021-07-12 10:28:19 浏览: 评论:0 

这篇文章主要介绍了PHP使用Memcache时模拟命名空间及缓存失效问题的解决,这里谈到的缓存失效主要针对高并发场景下取不到缓存的情况,需要的朋友可以参考下

缓存命名空间

memcache本身不支持命名空间,但是我们可以利用 memcache本身的机制,来模拟命名空间。比如:你要清除一组数据,就需要用到命名空间,来看这样一个例子,说明写在了注释里:

  1. class Action 
  2.     
  3.  public function index() 
  4.  { 
  5.   global $mc_wr
  6.      
  7.   // 获取命名空间 
  8.   $ns_key = $mc_wr->get("foo_namespace_key"); 
  9.   // 如果命名空间不存在,则设置一个 
  10.   if($ns_key===false) $mc_wr->set("foo_namespace_key",time()); 
  11.      
  12.   $otherParms = 'select * from user LIMIT 1'
  13.   // 根据命名空间生成唯一的key 
  14.   $my_key = "foo_".$ns_key.'_'.md5($otherParms); 
  15.      
  16.   // 获取当前key下的缓存 
  17.   $val = $mc_wr->get($my_key); 
  18.   if (!$val) { 
  19.    $value = 'wangdekang_'.time(); 
  20.    // 缓存不存在则设置缓存 600秒, 0为随机失效时间, 为失效时间添加随机秒数,防止瞬间所有缓存同时失效 
  21.    $mc_wr->set($my_key,$value,600, 0); 
  22.   } 
  23.      
  24.   echo $val
  25.  } 
  26.     
  27.  public function clear_ns() 
  28.  { 
  29.   global $mc_wr
  30.   // 更新命名空间值,让当前命名空间的所有值失效, memcache自身的缓存失效机制,当缓存不在被访问,会通过LRU失效机制 
  31.   $mc_wr->set('foo_namespace_key', time()); 
  32.  } 

memcache缓存失效问题

在大并发的场合,当cache失效时,大量并发同时取不到cache,会同一瞬间去访问db并回设cache,可能会给系统带来潜在的超负荷风险。

解决方法:

方法一

在load db之前先add一个mutex key, mutex key add成功之后再去做加载db, 如果add失败则sleep之后重试读取原cache数据,为了防止死锁,mutex key也需要设置过期时间,伪代码如下:

  1. if (memcache.get(key) == null) { 
  2.  // 3 min timeout to avoid mutex holder crash 
  3.  if (memcache.add(key_mutex, 3 * 60 * 1000) == true) { 
  4.   value = db.get(key); 
  5.   memcache.set(key, value); 
  6.   memcache.delete(key_mutex); 
  7.  } else { 
  8.   sleep(50); 
  9.   retry(); 
  10.  } 

方法二

在value内部设置1个超时值(timeout1), timeout1比实际的memcache

timeout(timeout2)小。当从cache读取到timeout1发现它已经过期时候,马上延长timeout1并重新设置到cache,然后再从数据库加载数据并设置到cache中,伪代码如下:

  1. v = memcache.get(key); 
  2. if (v == null) { 
  3.  if (memcache.add(key_mutex, 3 * 60 * 1000) == true) { 
  4.   value = db.get(key); 
  5.   memcache.set(key, value); 
  6.   memcache.delete(key_mutex); 
  7.  } else { 
  8.   sleep(50); 
  9.   retry(); 
  10.  } 
  11. else { 
  12.  if (v.timeout <= now()) { 
  13.   if (memcache.add(key_mutex, 3 * 60 * 1000) == true) { 
  14.    // extend the timeout for other threads 
  15.    v.timeout += 3 * 60 * 1000; 
  16.    memcache.set(key, v, KEY_TIMEOUT * 2); 
  17.  
  18.    // load the latest value from db 
  19.    v = db.get(key); 
  20.    v.timeout = KEY_TIMEOUT; 
  21.    memcache.set(key, value, KEY_TIMEOUT * 2); 
  22.    memcache.delete(key_mutex); 
  23.   } else { 
  24.    sleep(50); 
  25.    retry(); 
  26.   } 
  27.  } 
  28. }

Tags: Memcache PHP命名空间

分享到: