`
lovnet
  • 浏览: 6906803 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

遍历memcached缓存对象(C#)

阅读更多

STATS命令

出于性能考虑,memcached没有提供遍历功能,不过我们可以通过以下两个stats命令得到所有的缓存对象。

1、stats items

显示各个slab中item的数目。

2、stats cachedump slab_idlimit_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

代码
<!-- <br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />--> /// <summary>
/// 获取服务器端缓存的数据信息
/// </summary>
/// <paramname="serverArrayList"> 要访问的服务列表 </param>
/// <returns> 返回信息 </returns>
public static ArrayListGetStats(ArrayListserverArrayList,StatsstatsCommand, string param)
{
ArrayListstatsArray = new ArrayList();
param = Utils.StrIsNullOrEmpty(param) ? "" :param.Trim().ToLower();

string commandstr = " stats " ;
// 转换stats命令参数
switch (statsCommand)
{
case Stats.Reset:{commandstr = " statsreset " ; break ;}
case Stats.Malloc:{commandstr = " statsmalloc " ; break ;}
case Stats.Maps:{commandstr = " statsmaps " ; break ;}
case Stats.Sizes:{commandstr = " statssizes " ; break ;}
case Stats.Slabs:{commandstr = " statsslabs " ; break ;}
case Stats.Items:{commandstr = " stats " ; break ;}
case Stats.CachedDump:
{
string []statsparams = Utils.SplitString(param, " " );
if (statsparams.Length == 2 )
if (Utils.IsNumericArray(statsparams))
commandstr = " statscachedump " + param;

break ;
}
case Stats.Detail:
{
if ( string .Equals(param, " on " ) || string .Equals(param, " off " ) || string .Equals(param, " dump " ))
commandstr = " statsdetail " + param.Trim();

break ;
}
default :{commandstr = " stats " ; break ;}
}
// 加载返回值
Hashtablestats = MemCachedManager.CacheClient.Stats(serverArrayList,commandstr);
foreach ( string key in stats.Keys)
{
statsArray.Add(key);
Hashtablevalues = (Hashtable)stats[key];
foreach ( string key2 in values.Keys)
{
statsArray.Add(key2 + " : " + values[key2]);
}
}
return statsArray;
}

MemCachedClient.Stats

代码
<!-- <br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->public HashtableStats(ArrayListservers, string command)
{

// getSockIOPoolinstance
SockIOPoolpool = SockIOPool.GetInstance(_poolName);

// returnfalseifunabletogetSockIOobj
if (pool == null )
{
// if(log.IsErrorEnabled)
// {
// log.Error(GetLocalizedString("unabletogetsocketpool"));
// }
return null ;
}

// getallserversanditerateoverthem
if (servers == null )
servers = pool.Servers;

// ifnoservers,thenreturnearly
if (servers == null || servers.Count <= 0 )
{
// if(log.IsErrorEnabled)
// {
// log.Error(GetLocalizedString("statsnoservers"));
// }
return null ;
}

// arrayofstatsHashtables
HashtablestatsMaps = new Hashtable();

for ( int i = 0 ;i < servers.Count;i ++ )
{

SockIOsock = pool.GetConnection(( string )servers[i]);
if (sock == null )
{
// if(log.IsErrorEnabled)
// {
// log.Error(GetLocalizedString("unabletoconnect").Replace("$$Server$$",servers[i].ToString()));
// }
continue ;
}

// buildcommand
command = Discuz.Common.Utils.StrIsNullOrEmpty(command) ? " stats\r\n " :command + " \r\n " ;

try
{
sock.Write(UTF8Encoding.UTF8.GetBytes(command));
sock.Flush();

// maptoholdkeyvaluepairs
Hashtablestats = new Hashtable();

// loopoverresults
while ( true )
{
string line = sock.ReadLine();
// if(log.IsDebugEnabled)
// {
// log.Debug(GetLocalizedString("statsline").Replace("$$Line$$",line));
// }

if (line.StartsWith(STATS))
{
string []info = line.Split( ' ' );
string key = info[ 1 ];
string val = info[ 2 ];

// if(log.IsDebugEnabled)
// {
// log.Debug(GetLocalizedString("statssuccess").Replace("$$Key$$",key).Replace("$$Value$$",val));
// }

stats[key] = val;

}
else if (END == line)
{
// finishwhenwegetendfromserver
// if(log.IsDebugEnabled)
// {
// log.Debug(GetLocalizedString("statsfinished"));
// }
break ;
}

statsMaps[servers[i]] = stats;
}
}
catch // (IOExceptione)
{
// if(log.IsErrorEnabled)
// {
// log.Error(GetLocalizedString("statsIOException"),e);
// }

try
{
sock.TrueClose();
}
catch // (IOException)
{
// if(log.IsErrorEnabled)
// {
// log.Error(GetLocalizedString("failedtoclosesomesocket").Replace("$$Socket$$",sock.ToString()));
// }
}

sock = null ;
}

if (sock != null )
sock.Close();
}

return statsMaps;
}

有了这两个方法我们就可以得到memcached中的缓存项了。

基本思路是,先得到cache中所有的item(stats items),再通过itemid 取出cachekey和cachevalue(stats cachedump)

程序实现如下:

<!-- <br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />--> private void GetItems()
{
ArrayListitemarr = new ArrayList();

ArrayListarrayList = new ArrayList();
StringBuildersb = new StringBuilder();

foreach ( string server in MemCachedManager.ServerList)
{
arrayList.Add(server);
}
ArrayListarr = MemCachedManager.GetStats(arrayList,MemCachedManager.Stats.Items, null );
foreach ( string a in arr)
{
string []tmparr = a.Split( ' : ' );
if (tmparr.Length > 1 )
{
int item_id = 0 ;
int .TryParse(tmparr[ 1 ], out item_id);

bool find = false ;
foreach ( int item in itemarr)
{
if (item == item_id)
find = true ;
}
if ( ! find && item_id > 0 && item_id != 11211 )
itemarr.Add(item_id);
}
}
foreach ( int item in itemarr)
{
sb.Append( " item " + item + " <br/> " );
ArrayListcachearr = MemCachedManager.GetStats(arrayList,MemCachedManager.Stats.CachedDump, "" + item + " 10 " );
foreach ( string cache in cachearr)
{
sb.Append(cache);
sb.Append( " <br/> " );
}
}
Response.Write(sb.ToString());
}

运行程序:

为什么没有输出缓存项呢?

DiscuzNT3.0中的bug

于是我找啊找,发现是DiscuzNT3.0中的一个bug导致。

在MemCachedClient.Stats中,有这样的一段代码:

<!-- <br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->if (line.StartsWith(STATS))
{
string []info = line.Split( ' ' );
string key = info[ 1 ];
string val = info[ 2 ];
stats[key] = val;

}
else if (END == line)
{
break ;
}

原来是忽略了stats cachedump 的结果是以ITEM开头的,所以什么都没有输出。简单修改一下:

<!-- <br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->if (line.StartsWith(STATS))
{
string []info = line.Split( ' ' );
string key = info[ 1 ];
string val = info[ 2 ];
stats[key] = val;

}
else if (line.StartsWith( " ITEM " ))
{
string []info = line.Split( ' [ ' );
string key = info[ 0 ].Split( ' ' )[ 1 ];
string val = " [ " + info[ 1 ];

stats[key] = val;
}
else if (END == line)
{
break ;
}

再看一下输出结果,显示正常。

分享到:
评论

相关推荐

    .net c# memcached缓存获取所有缓存键的方法步骤.docx

    .NET C# Memcached 缓存获取所有缓存键的方法步骤 在软件开发中,缓存机制是提高系统性能和减少数据库访问频次的重要手段之一。Memcached 是一种流行的分布式缓存系统,广泛应用于各种 Web 应用程序中。.NET 平台下...

    C# memcached缓存使用实例代码

    在IT行业中,缓存是一种非常...总之,C#中使用Memcached缓存的关键在于选择合适的客户端库,理解和运用其提供的API,以及根据业务需求实现相应的缓存策略。通过合理的缓存管理,可以显著提升应用程序的性能和响应速度。

    .net/c# memcached缓存获取所有缓存键的方法步骤

    在.NET/C#环境中,Memcached是一种常用的分布式内存缓存系统,用于提高应用程序的性能和响应速度。MemcachedDotNet_clientlib-1.1.5是一个.NET客户端库,它允许开发者与Memcached服务器进行交互。本篇文章将详细讲解...

    memcached数据完整迁移到redis

    Memcached 是一个广泛使用的分布式内存对象缓存系统,它能提高 Web 应用程序的性能。它通过将数据存储在内存中,提供快速的访问速度。Memcached 的主要特点包括简单的键值对存储、内存优化的数据结构以及基于内存的...

    c#编写的搜索引擎源码

    在C#中,可以利用Task并行库(TPL)进行并发处理,Entity Framework用于数据库操作,Redis或Memcached作为缓存解决方案。 总之,C#编写的搜索引擎源码是一个综合性的项目,涵盖了网络爬虫技术、HTML解析、文本处理...

    C#\企业面试题汇总

    2. **优化100万条记录的查询**:可以考虑建立合适的索引、分页查询、减少JOIN操作、使用存储过程、数据分区、内存缓存(如Redis或Memcached)等策略来提升查询效率。 3. **string与StringBuilder的区别**:string是...

    一般企业.net面试题总汇

    【替换Session和Cookie】Session和Cookie用于存储用户会话数据,但在分布式环境中,可以使用Memcached这样的分布式缓存服务来实现跨服务器的数据共享。 【变量交换】在不依赖第三个变量的情况下,可以通过线性运算...

    dbEntry数据库操作通用类样例

    7. **缓存支持**:为了提高性能,某些实现可能会集成缓存机制,如Redis或Memcached,将频繁查询的结果缓存起来。 在提供的`samples`目录下,你可以找到示例代码,展示了如何在实际应用中使用`dbEntry`类进行数据库...

    漂亮无限级分类源代码(三层实现).zip

    - **缓存策略**:为了提高性能,可能需要实现缓存机制,如Redis或Memcached,减少数据库的频繁访问。 - **懒加载**:对于大型分类树,只在需要时加载子分类,而不是一次性加载所有数据。 6. **扩展性**:源代码...

    YouZack.CommonLibraries

    为了提高性能,库可能实现了内存缓存或分布式缓存的功能,例如使用Redis或Memcached,这有助于减少不必要的数据库访问。 8. **数学计算与算法** 对于需要进行数学运算或者算法处理的场景,库可能包含了一些预定义...

    .NET技术学习大纲

    同时,了解遍历集合时`foreach`循环的用法,以及如何生成随机数。 - **常用类库**:掌握`String`与`StringBuilder`的使用场景,理解可空类型的重要性,并熟练使用文件操作相关的类,如`File`、`Directory`、`...

Global site tag (gtag.js) - Google Analytics