簡體   English   中英

檢查Memcache中是否存在密鑰

[英]Check if a key exists in Memcache

如何在沒有提取的情況下將值存儲在Memcache中,如何檢入PHP? 我不喜歡抓取它,因為我設置的值都是1MB大小,在我獲取它之后,我沒有用它,所以我浪費資源。 我在腳本中使用它來檢查某些鍵是否緩存在memcache中,如果沒有,它會從慢速數據源讀取它們並將它們設置在memcache中。

編輯:如果我使用Memcached::appendNULL Memcached::append到我正在檢查的鍵上怎么辦? 成功時返回TRUE ,失敗時返回FALSE 如果密鑰不存在, Memcached::getResultCode將返回Memcached::RES_NOTSTORED 這樣我檢查密鑰是否存在,它應該把密鑰放在LRU列表的頂部嗎?

謝謝。

我想知道為什么Memcached沒有特殊的方法。 以下是我在考慮之后得出的結論:

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

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

我不確定這對你有什么幫助,但你可以使用

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

如果密鑰已存在,它將返回false。

如果返回true,您可以使用

Memcache::delete  (  string $key)

刪除剛剛設置的密鑰。 這樣您就不需要獲取數據了。

基本上你想要做的就是用你的數據填充memcached,對吧?

問題是在沒有檢索值的情況下詢問密鑰是否存在並不是很有用。 看這種情況:

你問一個密鑰是否存在,它確實存在。 在您詢問之后,密鑰的數據將從緩存中排除。 雖然你的回復表明日期已經存在,但實際情況是數據不存在。 所以你沒時間問,因為答案與現實不同。

我想你想要做的是詢問一個密鑰是否存在,然后如果沒有,請填寫您的數據。 為什么不直接填寫所有數據? 順便說一句,您是否考慮過在使用數據填充memcached時,您可能正在驅逐剛才插入的密鑰?

我已經通過使用Memcached :: append解決了這個問題。 我嘗試追加值NULL,如果返回TRUE,則表示密鑰存在。 如果返回FALSE則表示密鑰不存在。 如果密鑰存在,它也將把它放在LRU列表的頂部。

我不喜歡添加/刪除建議,因為它會插入應用程序可能依賴的無效數據。 如果您的應用程序確實做出了這個假設,那么由於它引入的競爭條件,它會導致一個經常發生的細微錯誤。

一個解決方案是查看值,如果它的臨時數據假裝它不在那里,但這將要求所有應用程序代碼使用相同的api或者您需要更新應用程序本身,既不好玩也不容易出錯由於額外的復雜性。

如果該組鍵足夠小,您可以將其存儲在memcached中並使用它來確定是否再次從源中檢索數據。 但是,如果它的值大或者更大,那么這個方法更差,那么只需從memcached獲取整個值。

然后,您可以通過使用索引將密鑰分成較小的集合來解決新問題(當然,這是一種分析此數據的好方法,因此每個存儲桶都具有一定的大小,然后說起來就更容易了。)

實現將包括使用memcached append或prepend來維護與某些主密鑰綁定的密鑰列表或主密鑰,這些密鑰指向一組指向密鑰本身的子密鑰:)

無論哪種方式,你使應用程序越來越復雜,所以我只建議這樣做,如果確實存在瓶頸(如果需要經常通過網絡檢查密鑰存在),或者可用性如何關注(延遲)。

在我的情況下,我不會這樣做,因為我只會通過localhost訪問memcached並使用它作為我的應用程序的更多擴展,以緩存需要花費幾秒鍾才能正常加載的資源。

根本不可能,不能檢查是否存在密鑰。 最好使用true / false值創建單獨的鍵以檢查是否存在鍵

memcached現在有cas命令。 你可以使用cas唯一的0來獲得EXISTS或NOT_FOUND響應:

$ telnet localhost 11211
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
set hello 0 0 5
12345
STORED
gets hello
VALUE hello 0 5 6743
12345
END
cas hello 0 0 0 0

EXISTS
cas foo 0 0 0 0 

NOT_FOUND

在上面的腳本中,我首先使用set命令設置一個值為12345的密鑰hello。然后將其取回,這也返回了一個cas唯一的6743.然后我嘗試使用cas命令將值替換為nothing,但是因為我使用的cas唯一是0,我得到了EXISTS錯誤。

最后我嘗試使用cas設置一個不存在的密鑰foo並返回NOT_FOUND錯誤。

因為memcached對cas unique使用全局遞增值,所以使用0是安全的,它對您嘗試設置的項無效,如果確實存在則會返回EXISTS錯誤。

對不起,不熟悉php的memcache客戶端把它放在php代碼中。

最簡單的方法是獲取給定的密鑰並將其轉換為布爾值。

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

(討論稍晚,但是)實際上你可以訪問存儲在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)

從Memcached的角度來看,這沒有任何意義。 如果你想避免緩慢的數據源(通過預定的作業,我推測?),將數據保存到預定作業中更快但仍然穩定的數據源(例如文件)。 當您需要數據時,首先嘗試從Memcached讀取,如果失敗則讀取文件並將其保存到Memcached中。

Memcached無法給你一個好的答案,因為pakore已經回答了。 該體系結構並不意味着是一個穩定的數據源。

我需要一個可靠的測試來知道使用memcache Set或memcache替換。

這就是我最終的結果。

另一個選擇是設置一個到memcache查詢的網絡套接字,但最終它會做同樣的事情並且這個連接已經存在,這節省了制作和維護另一個連接的開銷,就像Joel Chen的回答一樣。

$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);
}

現在,如果你有“大數據”,那么解決方案就相當簡單了。 在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);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM