PHP使用Memcache時(shí)模擬命名空間及緩存失效問題的解決
緩存命名空間
memcache本身不支持命名空間,但是我們可以利用 memcache本身的機(jī)制,來模擬命名空間。比如:你要清除一組數(shù)據(jù),就需要用到命名空間,來看這樣一個(gè)例子,說明寫在了注釋里:
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)緩存不在被訪問,會(huì)通過LRU失效機(jī)制
$mc_wr->set('foo_namespace_key', time());
}
}
memcache緩存失效問題
在大并發(fā)的場(chǎng)合,當(dāng)cache失效時(shí),大量并發(fā)同時(shí)取不到cache,會(huì)同一瞬間去訪問db并回設(shè)cache,可能會(huì)給系統(tǒng)帶來潛在的超負(fù)荷風(fēng)險(xiǎn)。
解決方法:
方法一
在load db之前先add一個(gè)mutex key, mutex key add成功之后再去做加載db, 如果add失敗則sleep之后重試讀取原cache數(shù)據(jù)。為了防止死鎖,mutex key也需要設(shè)置過期時(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)過期時(shí)候,馬上延長(zhǎng)timeout1并重新設(shè)置到cache。然
后再?gòu)臄?shù)據(jù)庫加載數(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();
}
}
}
- 在Mac OS的PHP環(huán)境下安裝配置MemCache的全過程解析
- PHP保存session到memcache服務(wù)器的方法
- 在php中設(shè)置session用memcache來存儲(chǔ)的方法總結(jié)
- PHP擴(kuò)展Memcache分布式部署方案
- PHP環(huán)境中Memcache的安裝和使用
- windows下安裝php5.2.*,php5.3.*,php5.4.*版本的memcache擴(kuò)展
- PHP實(shí)現(xiàn)的memcache環(huán)形隊(duì)列類實(shí)例
- php中memcache 基本操作實(shí)例
- 在win系統(tǒng)安裝配置 Memcached for PHP 5.3 圖文教程
- php模塊memcache和memcached區(qū)別分析
相關(guān)文章
通過PHP的Wrapper無縫遷移原有項(xiàng)目到新服務(wù)的實(shí)現(xiàn)方法
這篇文章主要介紹了通過PHP的Wrapper無縫遷移原有項(xiàng)目到新服務(wù)的實(shí)現(xiàn)方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04
PHP與服務(wù)器文件系統(tǒng)的簡(jiǎn)單交互
這篇文章主要介紹了PHP與服務(wù)器文件系統(tǒng)的簡(jiǎn)單交互的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,感興趣的朋友一起看看吧2016-10-10
通過dbi使用perl連接mysql數(shù)據(jù)庫的方法
這篇文章主要介紹了通過dbi使用perl連接mysql數(shù)據(jù)庫的方法,需要的朋友可以參考下2014-04-04
php 使用html5實(shí)現(xiàn)多文件上傳實(shí)例
在html沒有出來之前,要實(shí)現(xiàn)php多文件上傳比較麻煩,需要在form表單里面添加多個(gè)input file域。html5發(fā)布以后,我們可以使用input file的html5屬性multiple來實(shí)現(xiàn)多文件上傳,需要的朋友可以參考下2016-10-10
PHP調(diào)用FFmpeg實(shí)現(xiàn)視頻切片
這篇文章主要為大家詳細(xì)介紹了PHP如何調(diào)用FFmpeg實(shí)現(xiàn)視頻切片功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-02-02
laravel實(shí)現(xiàn)上傳圖片,并且制作縮略圖,按照日期存放的代碼
今天小編就為大家分享一篇laravel實(shí)現(xiàn)上傳圖片,并且制作縮略圖,按照日期存放的代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-10-10
win7 wamp 64位 php環(huán)境開啟curl服務(wù)遇到的問題及解決方法
這篇文章主要介紹了PHP簡(jiǎn)單開啟curl的方法,較為詳細(xì)的講述了PHP開啟curl函數(shù)庫的具體步驟與相關(guān)注意事項(xiàng),需要的朋友可以參考下2018-09-09

