如何使用PHP memcache扩展在memcached中删除具有相同前缀键的项


How to delete items with same prefix key in memcached using PHP memcache extension?

非常相似的问题已经发布并得到了回答。然而,到目前为止,我发现的每个解决方案都是使用php Memcached扩展而不是Memcache。我试图删除/过期所有以预定义键开始的memcache项。例如:so_something, so_something_else ...

经过一番研究,我想出了如何使用标准Memcache命令来做到这一点。但是,不幸的是,这将绊倒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);
}