【问题标题】:How can I query memcached with php to get a list of all its keys in storage?如何使用 php 查询 memcached 以获取其存储中所有键的列表?
【发布时间】:2020-06-24 18:50:17
【问题描述】:

我需要将 memcached 复制到另一个键值系统(couchbase)。如何查询 memcached 服务器的内容以获取其中的内容列表以便我可以将其复制过来?

【问题讨论】:

标签: php memcached


【解决方案1】:

所有这些用于 Memcache 的解决方案,所以这里是 Memcached

function getMemcachedKeys($host = '127.0.0.1', $port = 11211)
{

    $mem = @fsockopen($host, $port);
    if ($mem === FALSE) return -1;

    // retrieve distinct slab
    $r = @fwrite($mem, 'stats items' . chr(10));
    if ($r === FALSE) return -2;

    $slab = array();
    while (($l = @fgets($mem, 1024)) !== FALSE) {
        // sortie ?
        $l = trim($l);
        if ($l == 'END') break;

        $m = array();
        // <STAT items:22:evicted_nonzero 0>
        $r = preg_match('/^STAT\sitems\:(\d+)\:/', $l, $m);
        if ($r != 1) return -3;
        $a_slab = $m[1];

        if (!array_key_exists($a_slab, $slab)) $slab[$a_slab] = array();
    }

    // recuperer les items
    reset($slab);
    foreach ($slab AS $a_slab_key => &$a_slab) {
        $r = @fwrite($mem, 'stats cachedump ' . $a_slab_key . ' 100' . chr(10));
        if ($r === FALSE) return -4;

        while (($l = @fgets($mem, 1024)) !== FALSE) {
            // sortie ?
            $l = trim($l);
            if ($l == 'END') break;

            $m = array();
            // ITEM 42 [118 b; 1354717302 s]
            $r = preg_match('/^ITEM\s([^\s]+)\s/', $l, $m);
            if ($r != 1) return -5;
            $a_key = $m[1];

            $a_slab[] = $a_key;
        }
    }

    // close
    @fclose($mem);
    unset($mem);

    // transform it;
    $keys = array();
    reset($slab);
    foreach ($slab AS &$a_slab) {
        reset($a_slab);
        foreach ($a_slab AS &$a_key) $keys[] = $a_key;
    }
    unset($slab);

    return $keys;
}

【讨论】:

  • 这是目前最好的答案,尽管人们还没有投票;提问者用“d”询问有关 Memcached 的问题。我不知道为什么马克贝克的回答得到了这么多的支持。
  • 同意,最佳答案。
【解决方案2】:

内存缓存 >= 2.0.0

function getMemcacheKeys() {
    $memcache = new Memcache;
    $memcache->connect('127.0.0.1', 11211) 
       or die ("Could not connect to memcache server");

    $list = array();
    $allSlabs = $memcache->getExtendedStats('slabs');
    $items = $memcache->getExtendedStats('items');
    foreach($allSlabs as $server => $slabs) {
        foreach($slabs AS $slabId => $slabMeta) {
            $cdump = $memcache->getExtendedStats('cachedump',(int)$slabId);
            foreach($cdump AS $keys => $arrVal) {
                if (!is_array($arrVal)) continue;
                foreach($arrVal AS $k => $v) {                   
                    echo $k .'<br>';
                }
            }
        }
    }   
} 

【讨论】:

  • 我只想在这里指出,虽然它有效,但 cachedump 实际上是用于 memcached 调试目的,并不打算像这样使用。未来版本的 memcached 也可能不支持 cachedump。 (请参阅此处来自 memcached 核心贡献者之一的评论 8 code.google.com/p/memcached/issues/detail?id=187
  • Cachedump 似乎没有得到所有的密钥(我一直在尝试这样做,然后遇到了这个链接):code.google.com/p/memcached/wiki/NewProgrammingFAQ
  • 对我有用的一个小但很大的区别是getExtendedStats 函数中的 limit 参数,默认值为 just 100。更新:@ 987654325@
  • 这个函数有问题,因为它使memcache只读,至少在当前版本的memcache PECL(3.0.8)和memcached(1.4.21)中
  • @matija 您可以将 0 作为最终参数传递以完全消除限制
【解决方案3】:
  1. 根据报告https://www.php.net/manual/en/memcached.getallkeys.php#123793 函数Memcached::getAllKeys 从memcached 1.4.23 开始工作。此外,它不保证所有密钥的归还。
  2. @mark-baker、@maduka-jayalath 和其他人基于stats cachedump 提供的代码有限制,如果您在内存缓存中有数百万个密钥,则不会返回所有密钥。它对内存缓存服务器也有性能影响。

有一个库允许在 all 内存缓存键之间异步迭代而不会影响性能:https://github.com/qmegas/memcache-search 它甚至不需要安装任何 memcache 扩展。

【讨论】:

    【解决方案4】:

    感谢示例代码

    这里是如何删除一个或多个特定键

    我正在使用辅助类来删除缓存,因此您必须为函数提供对 memcache 连接的引用

    public static function removePriceCache(&$memcache, &$cacheAvailable) {
    
        if ($cacheAvailable == true) {
            $list = array();
            $allSlabs = $memcache->getExtendedStats('slabs');
            $items = $memcache->getExtendedStats('items');
            foreach ($allSlabs as $server => $slabs) {
                foreach ($slabs AS $slabId => $slabMeta) {
                    $cdump = $memcache->getExtendedStats('cachedump', (int) $slabId);
                    foreach ($cdump AS $keys => $arrVal) {
                        if (!is_array($arrVal))
                            continue;
                        foreach ($arrVal as $k => $v) {
                            //echo $k . '<br>';
    
                            if (stripos($k, "Price") !== false) {
                                $memcache->delete($k);
                            }
                        }
                    }
                }
            }
        }
    }
    

    这将删除所有包含“价格”一词的键..

    【讨论】:

      【解决方案5】:

      根据文档:
      https://www.php.net/manual/en/memcached.getallkeys.php

      PECL 内存缓存 >= 2.0.0

      $memcached->getAllKeys();
      

      【讨论】:

        猜你喜欢
        • 2011-01-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-15
        • 2015-03-14
        • 2013-11-17
        • 1970-01-01
        相关资源
        最近更新 更多