memcached緩存批量更新解決方案探討


眾所周知,Memcached 是一個高性能的分布式內存對象緩存系統,用於動態Web應用以減輕數據庫負載。

俺所在的公司經營的主要是基於web和wap兩個平台的手機游戲門戶網站,分布式緩存解決方法正好有用武之地,多平台共享使用memcache緩存數據 (php+mysql+memcache),確實很大程度的緩解訪問量過大對數據庫的壓力。但是,在享受便利的同時,同樣也遇到相信對大多數 memcache使用者都造成困擾的一個問題:大容量緩存數據的更新難題。

說起緩存數據更新,可能有些兄弟會說,memcached本身有::delete()方法可以去更新指定key的數據,是的,對顯式緩存key的數據我們 可以方便的進行更新,這個是沒問題的。我這里指的是指那種復雜的隱式緩存key的數據列表緩存更新問題。因為獲取列表時一般會有多個查詢條件或排序方式, 加上要指定數據列表的分頁,所以往往一個獲取數據的方法會產生一組具有相似key的緩存,遇到這種情況該怎么辦呢?

可能有些人還不明白,舉個例子吧,例如我需要寫一個獲取手機游戲列表的方法,因為獲取時需要根據手機型號,游戲類型等條件進行查詢,還要根據時間,下載數等方式排序。那么就有:
class DataClass{
......
/**
* 獲取游戲列表
*
* @param int
$modelId 機型ID
* @param int $gameType 游戲分類
* @return array  游戲列表
*/

function getGameList($modelId=null, $gameType = null, $orderKey = "id", $sort = "DESC", $page = 1, $pagePer = 10) {
/**指定一個具有唯一性的緩存key,也許大家還有別的命名方式,其實都行,只要保證唯一性就行了**/
$key = $this->memPrefix .
"game_list_" . $modelId . "_" . $gameType . "_" . $orderKey . "_" . $sort . "_" . $pagePer . "_" . $page ;  
......
}
......
}

當我更新或刪除了一個游戲后,就要把通過這個方法產生的所有緩存都要更新,這里就有問題了。memcached為了性能着想,沒有也不會提供對key檢索 的功能,也就是你不可能知道通過這個方法已經存在了哪些key,故一個個key的去更新是不可能的。於是就想,要是能把這里所有的key都放到統一標識的 一個組里就好了,這樣就能對這組key進行遍歷一個個更新,但這個緩存key組怎么存放呢。存到本地緩存,多平台間數據更新不同步;存到memcache 里,大量頻繁的對memcache的寫入更新,會堵塞獲取緩存的網絡通道,這個是我通過測試才知道這種方式都多傻的,后果就是memcache一下子變得 奇慢...,看種思路看來不行了。

去網上東找西找,終於找到另一種更新機制:由時間戳來決定是否更新。先貼寫的代碼:

/**
* 獲取游戲列表
*
* @param int
$modelId 機型ID
* @param int $gameType 游戲分類
* @return array  游戲列表
*/

function getGameList($modelId=null, $gameType = null, $orderKey = "id", $sort = "DESC", $page = 1, $pagePer = 10) {
/**指定一個具有唯一性的緩存key**/
$key = $this->memPrefix .
"game_list_" . $modelId . "_" . $gameType . "_" . $orderKey . "_" . $sort . "_" . $pagePer . "_" . $page ;  
/**這個方法產生的所有的緩存共用一個update key**/
$update_key = "game_list_update";
$list = $this->memcache->get($key);
/**獲取要更新數據的時間**/
$update_time = $this->memcache->get($update_key);
/**數據為空或寫入緩存的時間小於更新時間時則更新**/
if(empty ($list) || $list['update'] < $update_time){
/**查詢數據庫得到數據**/
$game_list = ...;
$list = array (
'data' => $game_list,
'update' => time(),                   
);
$this->memcache->set($key, $list, $this->policy);
}
return (!empty($list)) ? $list['data'] : null;
}


/**
* 更新緩存數據
*
* @access public
* @param string $update_key - 緩存更新key
*/

function updateMemcache($update_key) {
$update_key = $this->memPrefix . $update_key;
$this->memcache->set($update_key, time(), array (
'lifetime' => 0
));
}


更新緩存:
$data_class = new DataClass;
$data_class::updateMemcache("game_list_update");


相信大家應該從中看出這個思路吧。就是給數據緩存時加一個時間戳,用來與更新時間來進行比較,如果更新時間大於緩存時間,那就說明要進行更新了,否則直接取緩存數據。總算解決了隱式緩存key的數據更新問題!


轉於:www.kissthink.com/archive/memcached-caching-solutions-of-batch-update.html

http://blog.csdn.net/lxy2520/article/details/7734265

http://kb.cnblogs.com/page/69074/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM