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/
 
                    
                     
                    
                 
                    
                
 
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号