欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

PHP使用Memcache時(shí)模擬命名空間及緩存失效問(wèn)題的解決

 更新時(shí)間:2016年02月27日 15:57:12   作者:常思過(guò)  
這篇文章主要介紹了PHP使用Memcache時(shí)模擬命名空間及緩存失效問(wèn)題的解決,這里談到的緩存失效主要針對(duì)高并發(fā)場(chǎng)景下取不到緩存的情況,需要的朋友可以參考下

緩存命名空間

memcache本身不支持命名空間,但是我們可以利用 memcache本身的機(jī)制,來(lái)模擬命名空間。比如:你要清除一組數(shù)據(jù),就需要用到命名空間,來(lái)看這樣一個(gè)例子,說(shuō)明寫(xiě)在了注釋里:

class Action
{
  
 public function index()
 {
  global $mc_wr;
   
  // 獲取命名空間
  $ns_key = $mc_wr->get("foo_namespace_key");
  // 如果命名空間不存在,則設(shè)置一個(gè)
  if($ns_key===false) $mc_wr->set("foo_namespace_key",time());
   
  $otherParms = 'select * from user LIMIT 1';
  // 根據(jù)命名空間生成唯一的key
  $my_key = "foo_".$ns_key.'_'.md5($otherParms);
   
  // 獲取當(dāng)前key下的緩存
  $val = $mc_wr->get($my_key);
  if (!$val) {
   $value = 'wangdekang_'.time();
   // 緩存不存在則設(shè)置緩存 600秒, 0為隨機(jī)失效時(shí)間, 為失效時(shí)間添加隨機(jī)秒數(shù),防止瞬間所有緩存同時(shí)失效
   $mc_wr->set($my_key,$value,600, 0);
  }
   
  echo $val;
 }
  
 public function clear_ns()
 {
  global $mc_wr;
  // 更新命名空間值,讓當(dāng)前命名空間的所有值失效, memcache自身的緩存失效機(jī)制,當(dāng)緩存不在被訪問(wèn),會(huì)通過(guò)LRU失效機(jī)制
  $mc_wr->set('foo_namespace_key', time());
 }
}

memcache緩存失效問(wèn)題
在大并發(fā)的場(chǎng)合,當(dāng)cache失效時(shí),大量并發(fā)同時(shí)取不到cache,會(huì)同一瞬間去訪問(wèn)db并回設(shè)cache,可能會(huì)給系統(tǒng)帶來(lái)潛在的超負(fù)荷風(fēng)險(xiǎn)。
解決方法:

方法一
在load db之前先add一個(gè)mutex key, mutex key add成功之后再去做加載db, 如果add失敗則sleep之后重試讀取原cache數(shù)據(jù)。為了防止死鎖,mutex key也需要設(shè)置過(guò)期時(shí)間。偽代碼如下

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

方法二
在value內(nèi)部設(shè)置1個(gè)超時(shí)值(timeout1), timeout1比實(shí)際的memcache
timeout(timeout2)小。當(dāng)從cache讀取到timeout1發(fā)現(xiàn)它已經(jīng)過(guò)期時(shí)候,馬上延長(zhǎng)timeout1并重新設(shè)置到cache。然
后再?gòu)臄?shù)據(jù)庫(kù)加載數(shù)據(jù)并設(shè)置到cache中。偽代碼如下

v = memcache.get(key);
if (v == null) {
 if (memcache.add(key_mutex, 3 * 60 * 1000) == true) {
  value = db.get(key);
  memcache.set(key, value);
  memcache.delete(key_mutex);
 } else {
  sleep(50);
  retry();
 }
} else {
 if (v.timeout <= now()) {
  if (memcache.add(key_mutex, 3 * 60 * 1000) == true) {
   // extend the timeout for other threads
   v.timeout += 3 * 60 * 1000;
   memcache.set(key, v, KEY_TIMEOUT * 2);

   // load the latest value from db
   v = db.get(key);
   v.timeout = KEY_TIMEOUT;
   memcache.set(key, value, KEY_TIMEOUT * 2);
   memcache.delete(key_mutex);
  } else {
   sleep(50);
   retry();
  }
 }
}

相關(guān)文章

最新評(píng)論