检查Memcache中是否存在密钥

时间:2010-06-22 07:28:49

标签: php memcached

如果在不提取值的情况下将值存储在Memcache中,如何检入PHP?我不喜欢抓取它,因为我设置的值都是1MB大小,在我获取它之后,我没有用它,所以我浪费资源。我在脚本中使用它来检查某些键是否缓存在memcache中,如果没有,它会从慢速数据源读取它们并将它们设置在memcache中。

修改:如果我使用Memcached::appendNULL附加到我正在检查的密钥上会怎样?成功时返回TRUE或失败时返回FALSE。如果密钥不存在,Memcached::getResultCode将返回Memcached::RES_NOTSTORED。这样我检查密钥是否存在,它应该把密钥放在LRU列表的顶部吗?

谢谢。

11 个答案:

答案 0 :(得分:6)

我不确定这对你有什么帮助,但你可以使用

Memcache::add  (  string $key  ,  mixed $var)

如果密钥已经存在,它将返回false。

如果返回true,您可以使用

Memcache::delete  (  string $key)

删除刚设置的密钥。这样你就不需要获取数据了。

答案 1 :(得分:5)

我想知道为什么Memcached没有特殊的方法。以下是我在考虑之后得出的结论:

function has($key)
{
    $m->get($key)

    return \Memcached::RES_NOTFOUND !== $m->getResultCode();
}

答案 2 :(得分:3)

基本上你想要做的就是用你的数据填充memcached,对吧?

问题是在没有检索值的情况下询问密钥是否存在并不是很有用。见这种情况:

您询问密钥是否存在且确实存在。在您询问之后,密钥的数据将从缓存中排除。虽然你的回复表明日期已经存在,但实际情况是数据不存在。所以你没时间问,因为答案与现实不同。

我想你想要做的是询问密钥是否存在,然后如果不存在,请填写您的数据。为什么不直接填写所有数据?顺便说一句,您是否考虑过在使用数据填充memcached时,您可能正在驱逐刚才插入的密钥?

答案 3 :(得分:3)

我通过使用Memcached :: append解决了这个问题。我尝试追加值NULL,如果返回TRUE,则表示密钥存在。如果返回FALSE则表示密钥不存在。如果密钥存在,它也会将它放在LRU列表的顶部。

答案 4 :(得分:2)

我不喜欢添加/删除建议,因为它会插入应用程序可能依赖的无效数据。如果您的应用程序确实做出了这个假设,那么由于它引入的竞争条件,它会导致一个经常发生的细微错误。

一个解决方案是查看值,如果它的临时数据假装它不在那里,但这需要所有应用程序代码使用相同的api,或者你需要更新应用程序本身,既不好玩又由于额外的复杂性,有些容易出错。

如果该组键足够小,您可以将其存储在memcached中并使用它来确定是否再次从源中检索数据。但是,如果它的值大或者更大,那么这个方法就更差了,只需从memcached中获取整个值。

然后你可以通过使用索引将你的密钥分成更小的集合来解决新问题(当然这是一种分析这些数据的好方法,因此每个存储桶都是一定的大小,然后就这么说了。)

实现将包括使用memcached append或prepend来维护与某些主密钥绑定的密钥列表或主密钥,这些密钥指向一组指向密钥本身的子密钥:)

无论哪种方式,你都会使应用程序变得越来越复杂,所以我只建议在确实存在瓶颈的情况下执行此操作(如果需要经常通过网络检查密钥存在),或者如果关注的可用性(延迟)。

在我的情况下,我不会这样做,因为我只会通过localhost访问memcached并将其用作我的应用程序的更多扩展,以缓存需要花费几秒钟才能正常加载的资源。

答案 5 :(得分:1)

根本不可能,不可能只检查密钥是否存在。 最好使用true / false值创建一个单独的键来检查键的存在

答案 6 :(得分:1)

memcached现在有了cas命令。你可以使用cas唯一的0来获得EXISTS或NOT_FOUND响应:

<div class="main">
  <div class="inside"></div>
</div>

在上面的记录中,我首先使用set命令设置值为12345的密钥hello。然后将其取回,这也返回了一个cas唯一的6743。 然后我尝试使用cas命令替换没有任何值,但因为我使用的cas唯一是0,我得到了EXISTS错误。

最后我尝试使用cas设置一个不存在的密钥foo并返回NOT_FOUND错误。

因为memcached对cas unique使用全局递增值,所以使用0是安全的,它对您尝试设置的项无效,如果它存在,您将收到EXISTS错误。

抱歉,不熟悉php的memcache客户端,将其放入php代码中。

答案 7 :(得分:0)

从Memcached的角度来看,这没有任何意义。如果你想避免缓慢的数据源(通过预定的作业,我推测?),将数据保存到预定作业中更快但仍然稳定的数据源(例如文件)。当您需要数据时,首先尝试从Memcached读取,如果失败则读取文件并将其保存到Memcached中。

Memcached无法给你一个好的答案,因为pakore已经回答了。该架构并不意味着是一个稳定的数据源。

答案 8 :(得分:0)

最简单的方法是获取给定的密钥并将其转换为布尔值。

(bool) Memcache::get(string $key)

答案 9 :(得分:0)

(讨论稍晚,但是)实际上你可以访问存储在memcache中的所有键/值,按:

$allSlabs = $memcache->getExtendedStats('slabs');
$items = $memcache->getExtendedStats('items');

foreach ($allSlabs as $server => $slabs)
   foreach ($slabs as $slabId => $slabMeta)
       foreach ($memcache->getExtendedStats('cachedump', (int) $slabId) as $entries)
           if (!empty($entries))
               foreach ($entries as $key => $entry)

答案 10 :(得分:0)

我需要一个可靠的测试来知道使用memcache Set或memcache替换。

这就是我最终的结果。

另一个选择是设置一个到memcache查询的网络套接字,但最后它会最终做同样的事情并且这个连接已经存在,这节省了制作和维护另一个连接的开销,就像Joel Chen和# 39;答案。

$key = 'test';
$value = 'foobarbaz';
/**
 * Intricate dance to test if key exists.
 * If it doesn't exist flags will remain a boolean and we need to use the method set.
 * If it does exist it'll be set to integer indicating the compression and what not, then we need to use replace.
 */
$storageFlag = (is_null($value) || is_bool($value) || is_int($value) || is_float($value) ? false : MEMCACHE_COMPRESSED);
$flags = false;
$memcache->get($key, $flags);
if(false === $flags) {
    $memcache->set($key, $value, storageFlag  , $minutes);
}
else {
    $memcache->replace($key, $value, storageFlag, $minutes);
}

现在,如果你有&#34;大数据&#34;解决方案相当简单。在cojoin中使用第二个键,它包含一个像整数一样简单的东西来检查。总是一起使用它们,你没有问题。

$key = 'test';
$value = 'foobarbaz';

$storageFlag = (is_null($value) || is_bool($value) || is_int($value) || is_float($value) ? false : MEMCACHE_COMPRESSED);
$flags = false;
$exist_key = $key.'_exists';

$memcache->get($exist_key, $flags);
if(false === $flags) {
    $memcache->set($key, $value, storageFlag  , $minutes);
    $memcache->set($exist_key, 42, false  , $minutes);
}
else {
    $memcache->replace($key, $value, storageFlag, $minutes);
    $memcache->replace($exist_key, 42, false  , $minutes);
}