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

时间:2016-11-08 19:58:32

标签: php memcached

已发布并回答了非常类似的问题。但是我到目前为止找到的每个解决方案都使用php Memcached extension而不是Memcache。我试图删除/过期所有以预定义键开头的memcache项。例如,so_somethingso_something_else ...。非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

经过一些研究后,我想到了如何使用标准的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);
}