如何使用 PHP memcache 扩展删除 memcached 中具有相同前缀键的项目?
How to delete items with same prefix key in memcached using PHP memcache extension?
已经发布并回答了非常相似的问题。然而,到目前为止我发现的每个解决方案都使用 php Memcached extension rather than Memcache。我正在尝试 delete/expire 所有以预定义键开头的内存缓存项目。例如,so_something
、so_something_else ...
。非常感谢任何帮助。
经过一些研究,我想出了如何使用标准 Memcache 命令来完成它。但是,不幸的是,这会导致访问内存缓存服务器,因此要小心使用;在我的例子中,它仅在部署后使用:
/**
* Helper function to expire memcache entries with a specific key prefix.
*
* @param string $key_prefix
* The memcache key prefix.
* @param array $servers
* Array of used memcache servers.
* @return array
*
*/
function memcache_delete_by_key($key_prefix = '', $servers = array()) {
$mc = new Memcache();
$delete_keys = array();
foreach ($servers as $server => $default) {
list($host, $port) = explode(':', $server);
$mc->addServer($host, $port);
// Extract all the keys from Memcache.
$stats = memcache_command($server, $port, "stats items");
$stat_lines = explode("\r\n", $stats);
$slabs = array();
$keys = array();
foreach ($stat_lines as $line) {
if (preg_match("/STAT items:([\d]+):number ([\d]+)/", $line, $matches)) {
if (isset($matches[1]) && !in_array($matches[1], $slabs)) {
$slabs[] = $matches[1];
$string = memcache_command($server, $port, "stats cachedump " . $matches[1] . " " . $matches[2]);
preg_match_all("/ITEM (.*?) /", $string, $matches);
$keys[] = $matches[1];
}
}
}
$delete_keys = call_user_func_array('array_merge', $keys);
// Locate all keys that begin with our prefix.
foreach ($delete_keys as $index => $key) {
// If strpos returns 0 (not false) then we have a match.
if (strpos($key, $key_prefix) === 0) {
$mc->delete($key);
}
}
}
return $delete_keys;
}
/*
* Helper function to send memcache commands to a given Memcache Server
*/
function memcache_command($server, $port, $command) {
$s = @fsockopen($server, $port);
if (!$s) {
return die("Cant connect to:" . $server . ":" . $port);
}
fwrite($s, $command . "\r\n");
$buf = "";
while ((!feof($s))) {
$buf .= fgets($s, 256);
// Stat says 'END'.
if (strpos($buf, "END\r\n") !== FALSE) {
break;
}
// Delete says DELETED or NOT_FOUND.
if (strpos($buf, "DELETED\r\n") !== FALSE || strpos($buf, "NOT_FOUND\r\n") !== FALSE) {
break;
}
// Flush_all says ok.
if (strpos($buf, "OK\r\n") !== FALSE) {
break;
}
}
fclose($s);
return ($buf);
}
已经发布并回答了非常相似的问题。然而,到目前为止我发现的每个解决方案都使用 php Memcached extension rather than Memcache。我正在尝试 delete/expire 所有以预定义键开头的内存缓存项目。例如,so_something
、so_something_else ...
。非常感谢任何帮助。
经过一些研究,我想出了如何使用标准 Memcache 命令来完成它。但是,不幸的是,这会导致访问内存缓存服务器,因此要小心使用;在我的例子中,它仅在部署后使用:
/**
* Helper function to expire memcache entries with a specific key prefix.
*
* @param string $key_prefix
* The memcache key prefix.
* @param array $servers
* Array of used memcache servers.
* @return array
*
*/
function memcache_delete_by_key($key_prefix = '', $servers = array()) {
$mc = new Memcache();
$delete_keys = array();
foreach ($servers as $server => $default) {
list($host, $port) = explode(':', $server);
$mc->addServer($host, $port);
// Extract all the keys from Memcache.
$stats = memcache_command($server, $port, "stats items");
$stat_lines = explode("\r\n", $stats);
$slabs = array();
$keys = array();
foreach ($stat_lines as $line) {
if (preg_match("/STAT items:([\d]+):number ([\d]+)/", $line, $matches)) {
if (isset($matches[1]) && !in_array($matches[1], $slabs)) {
$slabs[] = $matches[1];
$string = memcache_command($server, $port, "stats cachedump " . $matches[1] . " " . $matches[2]);
preg_match_all("/ITEM (.*?) /", $string, $matches);
$keys[] = $matches[1];
}
}
}
$delete_keys = call_user_func_array('array_merge', $keys);
// Locate all keys that begin with our prefix.
foreach ($delete_keys as $index => $key) {
// If strpos returns 0 (not false) then we have a match.
if (strpos($key, $key_prefix) === 0) {
$mc->delete($key);
}
}
}
return $delete_keys;
}
/*
* Helper function to send memcache commands to a given Memcache Server
*/
function memcache_command($server, $port, $command) {
$s = @fsockopen($server, $port);
if (!$s) {
return die("Cant connect to:" . $server . ":" . $port);
}
fwrite($s, $command . "\r\n");
$buf = "";
while ((!feof($s))) {
$buf .= fgets($s, 256);
// Stat says 'END'.
if (strpos($buf, "END\r\n") !== FALSE) {
break;
}
// Delete says DELETED or NOT_FOUND.
if (strpos($buf, "DELETED\r\n") !== FALSE || strpos($buf, "NOT_FOUND\r\n") !== FALSE) {
break;
}
// Flush_all says ok.
if (strpos($buf, "OK\r\n") !== FALSE) {
break;
}
}
fclose($s);
return ($buf);
}