stats命令遍历memcached缓存对象(C#)出于性能考虑,memcached不提供遍历功能,但是我们可以通过下面两个STATS命令获取所有缓存对象。1.stats items显示每个平板中的项目数。2.stats cachedump slab_id limit_num以以下显示格式显示一个slab中的第一个limit_num键列表:ITEM key _ name[value _ length b;Expire_time|access_time s]除了以上两个,memcached还提供了以下命令:3。统计数据4、统计数据重置5、统计数据malloc 6、统计数据地图7、统计数据大小8、统计数据板9、统计数据详细信息[开|关|转储]。请自行搜索。Memcached数据存储和内存分配将在后面写入。添加缓存在本地添加几个密钥,如下所示:。
因为程序是用c#调用的,客户端需要执行STATS命令,可以直接参考DiscuzNT3.0中的实现,DiscuzNT下载地址:http://download.comsenz.com/DiscuzNT/src/在Discuz中找到了这两个类:MemCached.cs和MemCachedClient.cs。下载程序后缓存项目。
我们要用到的方法有:MemCached .GetStats代码复制代码代码如下: ///summary ///获取服务器端缓存的数据信息////summary////param name=' ServerArraylist '要访问的服务列表/param /返回返回信息/返回公共静态数组列表GetStats(数组列表serverArrayList,Stats statsCommand,string param){ 0数组列表Stats数组=new ArrayList();param=Utils .StrIsNullOrEmpty(参数)?参数。修剪()。toLower();string commandstr=' stats//转换统计数据命令参数开关(统计命令){案例统计.reset : { commandstr=' stats reset ';打破;}案例统计malloc : { commandstr=' stats malloc ';打破;}案例统计maps : { commandstr=' stats maps ';打破;}案例统计size s : { commandstr=' stats size ';打破;}案例统计slab : { commandstr=' stats blades ';打破;}案例统计Items: { commandstr=' stats打破;}案例统计cacheddump : { string[]stats params=Utils .splitString(param ' ');if(statsparams .长度==2) if(Utils .IsNumericArray(stats params))commandstr=' stats cachedump ' param;打破;}案例统计详细信息: {如果(字符串等于(参数,“on”)| |字符串.Equals(param,“off”)| | string .Equals(param," dump "))commandstr=" stats detail " param .trim();打破;}默认值: { commandstr=' stats打破;} } //加载返回值hashtable stats=MemCachedManager .缓存客户端。Stats(serverraylist,commandstr);foreach(统计数据中的字符串键键){ stat数组.添加(键);哈希表值=(哈希表)stats[key];foreach(值中的字符串key2 .key){ stat数组.添加(键2 ': '值[键2]);} }返回statsArray} MemCachedClient .统计数据代码复制代码代码如下:公共哈希表统计(数组列表服务器,字符串命令){ //获取索基奥波尔实例索基奥波尔池=SockIOPool .GetInstance(_ poolName);//如果无法获取SockIO obj if(pool==null){//if(log),则返回假的.IsErrorEnabled) //{ //log .错误(GetLocalizedString('无法获取套接字池'));//}返回null} //如果(服务器==null)服务器=池,则获取所有服务器并迭代它们。服务器;//如果没有服务器,则提前返回if(servers==null || servers .Count=0) { //if(log .IsErrorEnabled) //{ //log .错误(get localized string(' stats no servers ');//}返回空哈希表的统计数据数组Hashtable stats map=new Hashtable();for(int I=0;我是服务器。计数;i ) { SockIO sock=pool .GetConnection((字符串)服务器[I]);if(sock==null) { //if(log .IsErrorEnabled) //{ //log .错误(GetLocalizedString('无法连接')。替换(' $$服务器$ $ ',服务器[i].ToString()));//}继续;} //构建命令命令=Discuz .常见。Utils。StrIsNullOrEmpty(命令)?统计信息 r n":命令" r n;试试{袜子.写(utf8编码.UTF8。GetBytes(命令));袜子flush();//保存键值对的映射Hashtable stats=new Hashtable();//当(true) { string line=sock时循环结果ReadLine();//if(log .IsDebugEnabled) //{ //log .调试(GetLocalizedString('stats line ').替换(' $$Line$$ ',Line));//} if(行开始开关(STATS)){ string[]info=line .拆分("");string key=info[1];string val=info[2];//if(log .IsDebugEnabled) //{ //log .调试(获取本地化字符串(“stats success”).替换(' $$Key$$ ',键)。替换(' $$Value$$ ',val));//} stats[key]=val;} else if(END==line) { //当我们从服务器//if(日志)获得结束时完成IsDebugEnabled) //{ //log .调试(get localized string(' stats finished ');//} break;} stats映射[服务器[I]]=stats;} } catch//(IOexception e){//if(log .IsErrorEnabled) //{ //log .错误(get localized string(' stats IOexception '),e);//}尝试{袜子.true close();} catch//(IOException) { //if(log .IsErrorEnabled) //{ //log .错误(GetLocalizedString('未能关闭某些套接字')。替换(' $$Socket$$ ',袜子.ToString()));//} } sock=null;}如果(袜子!=null)袜子close();}返回statsMaps}有了这两个方法我们就可以得到服务器中的缓存项了。
基本思路是,先得到躲藏中所有的项目(统计项目),再通过模块取出cachekey和cachevalue(stats cachedump)程序实现如下:复制代码代码如下: private void GetItems(){ ArrayList item arr=new ArrayList();ArrayList ArrayList=new ArrayList();StringBuilder sb=new StringBuilder();foreach(MemCachedManager中的字符串服务器。服务器列表){数组列表。添加(服务器);} ArrayList arr=MemCachedManager .GetStats(arrayList,MemCachedManager .统计项,空);foreach(arr中的字符串a){ string[]tmparr=a . Split(' : ');if (tmparr .长度1){ int item _ id=0;里面的TryParse(tmparr[1],out item _ id);bool find=falseforeach(项目arr中的int item){ if(item==item _ id)find=true;} if(!查找项目id 0项目身份证!=11211) itemarr .add(item _ id);} } foreach(项目arr中的(同Internationalorganizations)国际组织项){某人.追加(“item”item“br/”);ArrayList缓存arr=MemCachedManager .GetStats(arrayList,MemCachedManager .统计数据。CachedDump,""项"10");foreach(缓存arr中的字符串缓存){某人.追加(缓存);某人(某人的简写)追加('(br/');} }回应。给(某人)写信ToString());} 运行程序
为什么没有输出缓存项呢?DiscuzNT3.0中的病菌于是我找啊找,发现是DiscuzNT3.0中的一个病菌导致。在MemCachedClient .统计数据中,有这样的一段代码:复制代码代码如下: if(线路开始开关(STATS)){ string[]info=line .拆分("");string key=info[1];string val=info[2];stats[key]=val;} else if(END==line){ break;} 原来是忽略了stats cachedump的结果是以项目开头的,所以什么都没有输出。简单修改一下:复制代码代码如下: if(线路开始开关(STATS)){ string[]info=line .拆分("");string key=info[1];string val=info[2];stats[key]=val;} else if(行以(' ITEM ')开头{ string[]info=line .拆分('[');字符串键=信息[0]。拆分("")[1];字符串val='[' info[1];stats[key]=val;} else if(END==line){ break;} 再看一下输出结果,显示正常