在php提供的用於與memcached交互的擴展模塊中有memcached與memcache,前者提供方法getAllKeys用於遍歷全部Memcached服務器上的key,可是並不保證原子操做,然後者卻沒有提供任何方法,雖然在PHP官方
文檔中有人給出使用方法getExtendedStats來間接獲取Memcached服務器上的全部key,可是給出的代碼是有很多坑的,若是拿來就用,對於cluster的memcached服務器而言,有些問題就須要指出來。 php
下面將給出官方文檔中的代碼,並指出可能面臨的問題,代碼以下: java
<?php /*\* * Function to get all memcache keys * @author Manish Patel * @Created: 28-May-2010 \*/ 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) { foreach($arrVal AS $k => $v){ echo $k ."<br>"; } } } }//EO getMemcacheKeys() ?>
在上述代碼中,若是用於獲取單個memcached服務器上的key,是不存在任何問題,可是獲取鏈接池中的多個memcached全部key就存在問題,會發現打印出重複的key,問題就在於當使用getExtendedStats用去特定$slabID
上的信息時,返回的是鏈接池中全部的服務器上的特定$slabId 的存儲的keys信息。當$server爲"127.0.0.1:11214"且$slabId爲0將變量$cdump的信息打印出以下所示: 服務器
array(2) { ["127.0.0.1:11214"]=> array(1) { ["course_schools__??¨é?¨"]=> array(2) { [0]=> string(1) "0" [1]=> string(10) "1380635175" } } ["127.0.0.1:11216"]=> array(1) { ["monitorMemcache"]=> array(2) { [0]=> string(2) "10" [1]=> string(10) "1385635702" } } }
當$server爲"127.0.0.1:11216"且$slabId爲0將變量$cdump的信息打印出以下所示: memcached
array(2) { ["127.0.0.1:11214"]=> array(1) { ["course_schools__??¨é?¨"]=> array(2) { [0]=> string(1) "0" [1]=> string(10) "1380635175" } } ["127.0.0.1:11216"]=> array(1) { ["monitorMemcache"]=> array(2) { [0]=> string(2) "10" [1]=> string(10) "1385635702" } } }
也就是說,按照上述代碼循環,會遭遇遍歷不一樣memcached服務器時,對於某個$slabId,就有可能再次獲取其餘服務器此$slabId的信息(其餘服務器也含有$slabId的值),於是在memcached是鏈接池的情景,會出現key重複的狀況,使用上述代碼,
爲正確獲取且不重複遍歷鏈接池全部服務器的某特定$slabID信息,能夠先統計出鏈接池全部memcached服務器中的不重複$slabId,再獲取某$slabId信息,從而遍歷出不重複的全部key以及value內容,關鍵代碼片斷以下: spa
39 $allSlabs = $memcache->getExtendedStats('slabs'); 40 foreach($allSlabs as $server => $slabs) 41 { 42 foreach($slabs as $slabId => $slabInfo) 43 { 44 if(isset($allSlabIds[$slabId])) 45 { 46 continue; 47 } 48 49 $allSlabIds[$slabId] = 1; 50 } 51 } 52 53 //再打印出key
54 foreach($allSlabIds as $slabId => $counter) 55 { 56 $cdump = $memObj->getExtendedStats('cachedump',(int)$slabId); 57 foreach($cdump AS $keys => $arrVal)- 58 { 59 if (!is_array($arrVal)) continue; 60 foreach($arrVal AS $k => $v)- 61 { 62 echo $k ."<br>"; 63 } 64 } 65 }