我是memcached的新手。 此代码是否容易受到过期缓存竞争条件的影响? 你会如何改进它?
$memcache = new Memcache;
$memcache->connect('127.0.0.1');
$arts = ($memcache===FALSE) ? FALSE : $memcache->get($qparams);
if($arts===FALSE) {
$arts=fetchdb($q, $qparams);
$memcache->add($qparams, $arts, MEMCACHE_COMPRESSED, 60*60*24*3);
}
if($arts<>FALSE) {
// do stuff
} else {
// empty dataset
}
假设查询X获得100行。排在第50行之后的另一个过程(假设零售价格增加)。
答案 0 :(得分:3)
此代码是否容易受到过期缓存争用条件的影响?你会如何改进它?
是即可。如果两个(或多个)并发客户端尝试从缓存中获取相同的密钥并最终从数据库中提取它。您将在数据库上出现峰值,并且数据库将在一段时间内处于高负载状态。这称为缓存标记。有几种方法可以解决这个问题:
有关详细信息,请查看memcached faq。
假设查询X获得100行。 #50行后面的一点点被另一个流程修改(假设零售价格上涨)。
缓存中有三种类型的数据:
我通常做的是将对象保持为单独的键,然后在列表中使用缓存“指针”。在你的情况下,你在缓存中的某个地方有N个objets(假设键是1,2..N
),然后你有一个数组array(1,2,3,10,42...)
中的对象列表。当您决定使用对象加载列表时,从缓存加载列表键,然后从缓存加载实际对象(使用getMulti
来减少请求)。在这种情况下,如果任何对象得到更新,您只能在一个位置更新它,并且它会在任何地方自动更新(更不用说使用此技术可以节省大量空间)。
修改:决定添加更多关于前瞻时间到期的信息。
使用过期数据x
设置对象,并将其保存到数据库中,其过期日期为x+5minutes
。这是从缓存加载对象时执行的步骤:
time() - x < 0
)+ ":lock"
来完成此操作。您必须将此密钥设置为以尽可能短的数量到期(对于1秒的memcached)。希望这能解决所有问题:)
答案 1 :(得分:1)
您必须使包含已修改项目的任何缓存对象无效。您必须修改缓存机制以更细粒度级别存储项目,或使整个条目无效。
这与说你在一个缓存条目中缓存整个数据库基本相同。你要么已经过期,要么没有过期。