当前位置:Gxlcms > asp.net > asp.net(C#)遍历memcached缓存对象

asp.net(C#)遍历memcached缓存对象

时间:2021-07-01 10:21:17 帮助过:6人阅读

STATS命令

遍历memcached缓存对象(C#)转载之青草堂
出于性能考虑,memcached没有提供遍历功能,不过我们可以通过以下两个stats命令得到所有的缓存对象。
1、stats items

显示各个slab中item的数目。
2、stats cachedump slab_id limit_num
显示某个slab中的前limit_num个key列表,显示格式:ITEM key_name [ value_length b; expire_time|access_time s]
除了上面两个,memcached还提供了以下命令:

3、stats
4、 stats reset
5、 stats malloc
6、 stats maps
7、 stats sizes
8、 stats slabs
9、 stats detail [on|off|dump]
命 令的用法就不一一说了,请自行google。 关于memcached的数据存储和内存分配以后有机会再写。

添加 缓存
在本地添加几个key,如下:

程序实现
因为要用c#调用,所以需要客户端执行 STATS 命令,这个可以直接参考DiscuzNT3.0中的实现。
DiscuzNT下载地址:http://download.comsenz.com/DiscuzNT/src/
下载完程序以后,在Discuz.Cache项目中找到这两个类:MemCached.cs和MemCachedClient.cs。
我们要用到的方法有:
MemCached.GetStats
代码
代码如下:
  1. <br>/// <summary> <br>/// 获取服 务器端缓存的数据信息 <br>/// </summary> <br>/// <param name="serverArrayList">要访问的服务列表</param> <br>/// <returns>返 回信息</returns> <br>public static ArrayList GetStats(ArrayList serverArrayList, Stats statsCommand, string param) <br>{ <br>ArrayList statsArray = new ArrayList(); <br>param = Utils.StrIsNullOrEmpty(param) ? "" : param.Trim().ToLower(); <br>string commandstr = "stats"; <br>//转换stats命令参数 <br>switch (statsCommand) <br>{ <br>case Stats.Reset: { commandstr = "stats reset"; break; } <br>case Stats.Malloc: { commandstr = "stats malloc"; break; } <br>case Stats.Maps: { commandstr = "stats maps"; break; } <br>case Stats.Sizes: { commandstr = "stats sizes"; break; } <br>case Stats.Slabs: { commandstr = "stats slabs"; break; } <br>case Stats.Items: { commandstr = "stats"; break; } <br>case Stats.CachedDump: <br>{ <br>string[] statsparams = Utils.SplitString(param, " "); <br>if(statsparams.Length == 2) <br>if(Utils.IsNumericArray(statsparams)) <br>commandstr = "stats cachedump " + param; <br>break; <br>} <br>case Stats.Detail: <br>{ <br>if(string.Equals(param, "on") || string.Equals(param, "off") || string.Equals(param, "dump")) <br>commandstr = "stats detail " + param.Trim(); <br>break; <br>} <br>default: { commandstr = "stats"; break; } <br>} <br>//加载返回值 <br>Hashtable stats = MemCachedManager.CacheClient.Stats(serverArrayList, commandstr); <br>foreach (string key in stats.Keys) <br>{ <br>statsArray.Add(key); <br>Hashtable values = (Hashtable)stats[key]; <br>foreach (string key2 in values.Keys) <br>{ <br>statsArray.Add(key2 + ":" + values[key2]); <br>} <br>} <br>return statsArray; <br>} <br> <br>MemCachedClient.Stats <br>代码 <br><span><u></u></span> 代码如下:<pre class="brush:php;toolbar:false layui-box layui-code-view layui-code-notepad"><ol class="layui-code-ol"><li><br>public Hashtable Stats(ArrayList servers, string command) <br>{ <br>// get SockIOPool instance <br>SockIOPool pool = SockIOPool.GetInstance(_poolName); <br>// return false if unable to get SockIO obj <br>if(pool == null) <br>{ <br>//if(log.IsErrorEnabled) <br>//{ <br>// log.Error(GetLocalizedString("unable to get socket pool")); <br>//} <br>return null; <br>} <br>// get all servers and iterate over them <br>if (servers == null) <br>servers = pool.Servers; <br>// if no servers, then return early <br>if(servers == null || servers.Count <= 0) <br>{ <br>//if(log.IsErrorEnabled) <br>//{ <br>// log.Error(GetLocalizedString("stats no servers")); <br>//} <br>return null; <br>} <br>// array of stats Hashtables <br>Hashtable statsMaps = new Hashtable(); <br>for(int i = 0; i < servers.Count; i++) <br>{ <br>SockIO sock = pool.GetConnection((string)servers[i]); <br>if(sock == null) <br>{ <br>//if(log.IsErrorEnabled) <br>//{ <br>// log.Error(GetLocalizedString("unable to connect").Replace("$$Server$$", servers[i].ToString())); <br>//} <br>continue; <br>} <br>// build command <br>command = Discuz.Common.Utils.StrIsNullOrEmpty(command) ? "stats\r\n": command + "\r\n"; <br>try <br>{ <br>sock.Write(UTF8Encoding.UTF8.GetBytes(command)); <br>sock.Flush(); <br>// map to hold key value pairs <br>Hashtable stats = new Hashtable(); <br>// loop over results <br>while(true) <br>{ <br>string line = sock.ReadLine(); <br>//if(log.IsDebugEnabled) <br>//{ <br>// log.Debug(GetLocalizedString("stats line").Replace("$$Line$$", line)); <br>//} <br>if(line.StartsWith(STATS)) <br>{ <br>string[] info = line.Split(' '); <br>string key = info[1]; <br>string val = info[2]; <br>//if(log.IsDebugEnabled) <br>//{ <br>// log.Debug(GetLocalizedString("stats success").Replace("$$Key$$", key).Replace("$$Value$$", val)); <br>//} <br>stats[ key ] = val; <br>} <br>else if(END == line) <br>{ <br>// finish when we get end from server <br>//if(log.IsDebugEnabled) <br>//{ <br>// log.Debug(GetLocalizedString("stats finished")); <br>//} <br>break; <br>} <br>statsMaps[ servers[i] ] = stats; <br>} <br>} <br>catch//(IOException e) <br>{ <br>//if(log.IsErrorEnabled) <br>//{ <br>// log.Error(GetLocalizedString("stats IOException"), e); <br>//} <br>try <br>{ <br>sock.TrueClose(); <br>} <br>catch//(IOException) <br>{ <br>//if(log.IsErrorEnabled) <br>//{ <br>// log.Error(GetLocalizedString("failed to close some socket").Replace("$$Socket$$", sock.ToString())); <br>//} <br>} <br>sock = null; <br>} <br>if(sock != null) <br>sock.Close(); <br>} <br>return statsMaps; <br>} <br> <br>有了这两个方法我们就可以得到memcached中的缓存项了。 <br>基本思路是,先得到cache中所有的item(stats items),再通过itemid 取出cachekey和cachevalue(stats cachedump) <br>程序实现如下: <br><span><u></u></span> 代码如下:<pre class="brush:php;toolbar:false layui-box layui-code-view layui-code-notepad"><ol class="layui-code-ol"><li><br>private void GetItems() <br>{ <br>ArrayList itemarr = new ArrayList(); <br>ArrayList arrayList = new ArrayList(); <br>StringBuilder sb = new StringBuilder(); <br>foreach (string server in MemCachedManager.ServerList) <br>{ <br>arrayList.Add(server); <br>} <br>ArrayList arr = MemCachedManager.GetStats(arrayList, MemCachedManager.Stats.Items, null); <br>foreach (string a in arr) <br>{ <br>string[] tmparr = a.Split(':'); <br>if (tmparr.Length > 1) <br>{ <br>int item_id = 0; <br>int.TryParse(tmparr[1], out item_id); <br>bool find = false; <br>foreach (int item in itemarr) <br>{ <br>if (item == item_id) <br>find = true; <br>} <br>if (!find && item_id > 0 && item_id != 11211) <br>itemarr.Add(item_id); <br>} <br>} <br>foreach (int item in itemarr) <br>{ <br>sb.Append("item " + item + "<br />"); <br>ArrayList cachearr = MemCachedManager.GetStats(arrayList, MemCachedManager.Stats.CachedDump, "" + item + " 10"); <br>foreach (string cache in cachearr) <br>{ <br>sb.Append(cache); <br>sb.Append("<br />"); <br>} <br>} <br>Response.Write(sb.ToString()); <br>} <br> <br>运行程序: <br><img height="146" alt="" src="https://img.gxlcms.com//Uploads-s/new/2019-09-19-201919/20100304193840321.jpg" width="319" border="0"><br>为什么没有</li></ol></pre>输出缓存项呢? <br><br>DiscuzNT3.0中的bug <br><br>于是我找啊找,发现是DiscuzNT3.0中的一个bug导致。 <br><br>在MemCachedClient.Stats中,有这样的一段代码: <br><span><u></u></span> 代码如下:<pre class="brush:php;toolbar:false layui-box layui-code-view layui-code-notepad"><ol class="layui-code-ol"><li><br>if(line.StartsWith(STATS)) <br>{ <br>string[] info = line.Split(' '); <br>string key = info[1]; <br>string val = info[2]; <br>stats[ key ] = val; <br><br>} <br>else if(END == line) <br>{ <br>break; <br>} <br> <br>原来是忽略了stats cachedump 的结果是以ITEM开头的,所以什么都没有</li></ol></pre>输出。简单修改一下: <br><span><u></u></span> 代码如下:<pre class="brush:php;toolbar:false layui-box layui-code-view layui-code-notepad"><ol class="layui-code-ol"><li><br>if(line.StartsWith(STATS) ) <br>{ <br>string[] info = line.Split(' '); <br>string key = info[1]; <br>string val = info[2]; <br>stats[ key ] = val; <br><br>} <br>else if (line.StartsWith("ITEM")) <br>{ <br>string[] info = line.Split('['); <br>string key = info[0].Split(' ')[1]; <br>string val = "[" + info[1]; <br><br>stats[key] = val; <br>} <br>else if (END == line) <br>{ <br>break; <br>} <br> <br>再看一下</li></ol></pre>输出结果,显示正常。 <br><img alt="" src="http://images.cnblogs.com/cnblogs_com/tenghoo/memcached-3.jpg" border="0"> </li><li> </li><li> </li></ol></pre>

人气教程排行