我想在我的社交网站上实现memcached。作为一个社交网络,大多数数据都经常变化。
例如,如果我要将用户的10,000个朋友存储在缓存中,则无论何时添加朋友,都需要更新缓存。这很容易,但是当其他人将它们添加为朋友时,它也需要更新。仅仅在好友列表上就有很多更新。
还有一些用户博客和公告,这些博客和公告是不间断发布的新用户博客和公告,您只能在朋友列表中看到用户创建的博客和公告,所以我认为这很难缓存。
我可以看到可能缓存一些仅在用户更新其配置文件时更改的配置文件信息,但如果有100,000多个用户进行了大量缓存,则会为每个用户创建一个缓存记录。这是个好主意吗?
答案 0 :(得分:2)
我想说,在可能的情况下缓存是一个好主意....大多数时候,你可以从传统的RDBMS中快速地从memcached中提取项目(特别是如果你有复杂的连接等)。我目前采用这样的策略取得了巨大的成功,这是我从经验中学到的:
如果可能,无限期缓存,并在进行更改时写入新值。尽量不要进行显式删除,因为您可能会导致竞争条件对尝试更新缓存的数据进行多次并发访问。如果缓存中没有项目以防止上述问题(使用memcached“add”+循环中的短暂睡眠时间),也会实现锁定
如果可能,使用队列在后台刷新缓存。我的实现目前使用在后台+ beanstalkd中运行的多线程perl进程,从而防止了前端的延迟时间。大部分时间的变化都会导致短暂的滞后。
如果可能的话,使用memcached getmulti,许多单独的memcached调用确实加起来。
对缓存进行分层,检查项目时,首先检查本地数组,然后检查memcached,然后检查db。首次访问后,缓存结果在本地数组中,以防止在同一项的脚本执行中多次访问memcached。编辑:澄清一下,如果使用像PHP这样的脚本语言,本地数组只会在当前脚本执行时生存:)例如:
class Itemcache {
private $cached_items = array();
private $memcachedobj;
public function getitem($memcache_key){
if(isset($this->cached_items[$memcache_key])){
return $this->cached_items[$memcache_key];
}elseif($result = $this->memcachedobj->get($memcache_key)){
$this->cached_items[$memcache_key] = $result;
return $result;
}else{
// db query here as $dbresult
$this->memcachedobj->set($memcache_key,$dbresult,0);
$this->cached_items[$memcache_key] = $dbresult;
return $dbresult;
}
}
编写一个包装函数,实现上述缓存策略#4。
在memcached中使用一致的键结构,例如。 'userinfo_ {user.pk}'其中user.pk是rdbms中用户的主键。
如果您的数据需要后期处理,请尽可能在放入缓存之前进行此处理,每次点击该数据都会节省几个周期。