たとえば、同じプレフィックスを持ついくつかのキャッシュされたアイテムがあります。
'app_111111', 'app_222222', 'app_333333', ...
Memcachedコマンドでこのような「app_xxxxxx」アイテムを削除できますか?
Memcachedはそのままではこの機能を提供しないため、自分で構築する必要があります。
これを解決する方法は、アプリケーションでキーのグループのプレフィックス(または名前空間)を定義することです。 memcachedで設定したキーには、その前にそのプレフィックスが付いています。 Memcachedからコンテンツを「削除」するときはいつでも、プレフィックスを変更するだけです。そして、Memcachedでキーを検索するときはいつでも、そのプレフィックスをキーに追加します。
あなたの場合、プレフィックスをたとえばMyAppPrefix1
に設定することから始めて、キーはMyAppPrefix1::app_333333
、MyAppPrefix1::app_444444
として保存されます。
後でこれらのエントリを「削除」するときに、MyAppPrefix2
を使用するようにアプリケーションを設定します。次に、Memcachedからapp_333333
と呼ばれるキーを取得しようとすると、MyAppPrefix2::app_333333
が検索され、削除された場合と同じように最初は見つかりません。
PHPのこの関数はどうですか:
function deletekeysbyindex($prefix) {
$m = new Memcached();
$m->addServer('localhost', 11211);
$keys = $m->getAllKeys();
foreach ($keys as $index => $key) {
if (strpos($key,$prefix) !== 0) {
unset($keys[$index]);
} else {
$m->delete($key);
}
}
return $keys;
}
$ prefixで始まるキーを削除し、削除されたすべてのキーのリストを返します。共有サーバー上でこれを30,000以上のキーで実行したところ、かなり高速でした-おそらく1秒未満です。
Memcacheへの1回のリクエストでは、これを行うことはできません。私たちはこれを行うことができます:
public function clearByPrefix($prefixes = array()) {
$prefixes = array_unique($prefixes);
$slabs = $this->memcache->getExtendedStats('slabs');
foreach ($slabs as $serverSlabs) {
if ($serverSlabs) {
foreach ($serverSlabs as $slabId => $slabMeta) {
if (is_int($slabId)) {
try {
$cacheDump = $this->memcache->getExtendedStats('cachedump', (int) $slabId, 1000);
} catch (Exception $e) {
continue;
}
if (is_array($cacheDump)) {
foreach ($cacheDump as $dump) {
if (is_array($dump)) {
foreach ($dump as $key => $value) {
$clearFlag = false;
// Check key has prefix or not
foreach ($prefixes as $prefix) {
$clearFlag = $clearFlag || preg_match('/^' . preg_quote($prefix, '/') . '/', $key);
}
// Clear cache
if ($clearFlag) {
$this->clear($key);
}
}
}
}
}
}
}
}
}
}
次のようにこの関数を呼び出します。
$prefixes = array();
array_Push($prefixes, 'prefix1_');
array_Push($prefixes, 'prefix2_');
array_Push($prefixes, 'prefix3_');
$this->clearByPrefix($prefixes);
少し遅いですが、これは機能するハックです。 60万個のキーを持つサーバーでは、完了するまでに0.5秒かかりました。
$prefix = 'MyApp::Test';
$len = strlen($prefix);
$proc = popen('/usr/local/bin/memdump --servers=localhost', 'r');
while (($key = fgets($proc)) !== false) {
if (substr_compare($key, $prefix, 0, $len) === 0) {
$memcached->delete(substr($key, 0, -1));
}
}