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 缓存获取所有缓存键的方法步骤 在软件开发中,缓存机制是提高系统性能和减少数据库访问频次的重要手段之一。Memcached 是一种流行的分布式缓存系统,广泛应用于各种 Web 应用程序中。.NET 平台下...
在IT行业中,缓存是一种非常...总之,C#中使用Memcached缓存的关键在于选择合适的客户端库,理解和运用其提供的API,以及根据业务需求实现相应的缓存策略。通过合理的缓存管理,可以显著提升应用程序的性能和响应速度。
在.NET/C#环境中,Memcached是一种常用的分布式内存缓存系统,用于提高应用程序的性能和响应速度。MemcachedDotNet_clientlib-1.1.5是一个.NET客户端库,它允许开发者与Memcached服务器进行交互。本篇文章将详细讲解...
Memcached 是一个广泛使用的分布式内存对象缓存系统,它能提高 Web 应用程序的性能。它通过将数据存储在内存中,提供快速的访问速度。Memcached 的主要特点包括简单的键值对存储、内存优化的数据结构以及基于内存的...
在C#中,可以利用Task并行库(TPL)进行并发处理,Entity Framework用于数据库操作,Redis或Memcached作为缓存解决方案。 总之,C#编写的搜索引擎源码是一个综合性的项目,涵盖了网络爬虫技术、HTML解析、文本处理...
2. **优化100万条记录的查询**:可以考虑建立合适的索引、分页查询、减少JOIN操作、使用存储过程、数据分区、内存缓存(如Redis或Memcached)等策略来提升查询效率。 3. **string与StringBuilder的区别**:string是...
【替换Session和Cookie】Session和Cookie用于存储用户会话数据,但在分布式环境中,可以使用Memcached这样的分布式缓存服务来实现跨服务器的数据共享。 【变量交换】在不依赖第三个变量的情况下,可以通过线性运算...
7. **缓存支持**:为了提高性能,某些实现可能会集成缓存机制,如Redis或Memcached,将频繁查询的结果缓存起来。 在提供的`samples`目录下,你可以找到示例代码,展示了如何在实际应用中使用`dbEntry`类进行数据库...
- **缓存策略**:为了提高性能,可能需要实现缓存机制,如Redis或Memcached,减少数据库的频繁访问。 - **懒加载**:对于大型分类树,只在需要时加载子分类,而不是一次性加载所有数据。 6. **扩展性**:源代码...
为了提高性能,库可能实现了内存缓存或分布式缓存的功能,例如使用Redis或Memcached,这有助于减少不必要的数据库访问。 8. **数学计算与算法** 对于需要进行数学运算或者算法处理的场景,库可能包含了一些预定义...
同时,了解遍历集合时`foreach`循环的用法,以及如何生成随机数。 - **常用类库**:掌握`String`与`StringBuilder`的使用场景,理解可空类型的重要性,并熟练使用文件操作相关的类,如`File`、`Directory`、`...