分布式缓存:.NET分布式缓存同步的手段



其实对于性扩展无非是Scale Up(向上扩展)或者是Scale Out(向外扩展), 微软对此看法是个App缓存Cache最好是以它自己为物理边界进行读写而不要放到别处去这样带问题可能有对象序列化传送反序列化网络连接开销跨进程开销对于高性能站点来说都是不能忽视问题.出于对这些原因考虑微推荐作法不是把多个应用放在起在多台Server布署www. 而是将个App划分成若干个小应用布署到区别服务器下面关系图展示了这种关系, 这样每种应用就可以独立管理自己缓存Cache数据但是对于象用户数据这样通用数据仍然会存在多处.

两种解决方案为了解决缓存Cache同步问题有人想出了解决办法, 可以参考这两个地方这个是MS这里还有先来看看Peter这个吧, 主要思想就是把要放到缓存Cache里面东西加上层包装CacheControlItem, 实现代码请去原文出处下载.

每台机器都维护个WebFarm里面成员服务器列表如果有新服务器进来发现自己不在这个列表中则会通知其它服务器把它加到这个名单里面添加缓存Cache这程是这样 A服务器需要插入个新缓存Cache值它把这个项目插入到自己缓存Cache中然后用它个CacheControlItem并指定它缓存Cache策略(优先级缓存Cache生存时间)设定它动作即添加然后把这个结象序列化通过Web传送到每个成员服务器接受到这些数据服务器跟据这个对象Action指令把反序列化后对象加入到自己缓存Cache里面这样个同步过程就完成了移除缓存Cache对象过程和的类似只不过不需要传送对象只在包装类里面设定它Action为删除就可以了. 当然为了提高性能可以实现个异步侦听线程专门用来响应缓存Cache通知请求. 总体上讲这处办法效率比较低在数据量较大情况下可能会造成大量缓存Cache数据同步数据流

我们再来看看M$是如何做想法类似只不过它不在WebFarm成员服务器的间同步缓存Cache而只是保证每台机器不要读到已经失效缓存Cache数据当缓存Cache数据失效时(相关依赖数据被更新), 通过维护个需要通知服务器列表依次每台服务器上WebService如果当前服务器上存在这键值缓存Cache则使它失效.

这两个老外写东西似乎都比较啰索不过对初学者来说比较友好可以步步地知道这件事情来龙去脉理解会清楚更刻

Memcached到底有多快?看了这些如果还不满意那么您可以试试Memcached它可以运行在Win32平台下在上篇文章中我们已经提到了这个东西但是它在.Net平台下面究竟表现如何?是否能象在PHP平台下面样地优秀我们现在来做个简单测试, 对比使用.Net自带Cache和Memcached两种实现方式看看差距究竟有多大过程是这样分别生成10000个串对象并分别设定键值插入到缓存Cache中然后再取出来看看花费总时间. 服务器端:memcached-1.2.1-win32, 客户端: memcacheddotnet_clientlib-1.1.5, 服务器端使用也比较简单解压文件的后在命令行下面输入: c:\\memcached -d 先安装服务, 接着 c:\\memcached -d start就可以了详细使用思路方法见介绍说明文件 -h 是查看帮助, 测试环境如下: [Page]

Memcached服务器 : Win2003 sp1, Framework 2.0,P4 D 3.4G, 768MB 内存, 千兆网卡.
Memcached客户机 : Win2003 sp1, Framework 2.0,T2060, 1G内存( 沙加神舟笔记本;) ), 千兆网卡.
两台机器通过直连线相连.

.Net Cache单机测试 : P4 D 3.4G, 768MB 内存.

测试结果, 存取10000个条目时间:

Memcached
Set(秒) 1.48 1.37 1.48 1.37 1.46
Get(秒) 2.42 2.42 2.42 2.43 2.42

HttpRuntime.Cache
Set(秒) 0.015 0.015 0.015 0.015 0.015
Get(秒)
0.015 0.015 0.015 0.015 0.015


.Net内建缓存Cache测试代码HttpRuntime.Cache
protected void Page_Load(object sender, EventArgs e)
{
start = 200;
runs = 10000;

keyBase = \"testKey\";
obj = \"This is a test of an object blah blah es, serialization does not seem to slow things down so much. The gzip compression is horrible horrible performance, so we _disibledevent=> for( i = start; i < start+runs; i)
{
HttpRuntime.Cache.Add(keyBase + i, obj,null,.Web.Caching.Cache.NoAbsoluteExpiration,
TimeSpan.FromMinutes(1),.Web.Caching.CacheItemPriority.Normal,null);
}
long end = DateTime.Now.Ticks;
long time = end - begin;

Response.Write(runs + \" s: \" + TimeSpan(time). + \"ms<br />\");



begin = DateTime.Now.Ticks; [Page]
hits = 0;
misses = 0;
for( i = start; i < start+runs; i)
{
str = () HttpRuntime.Cache.Get(keyBase + i);
(str != null)
hits;

misses;
}
end = DateTime.Now.Ticks;
time = end - begin;

Response.Write(runs + \" gets: \" + TimeSpan(time). + \"ms\");
}
Memcached测试代码Memcached
Memcached.MemcachedBench
{
using ;
using .Collections;

using Memcached.ClientLibrary;

public MemcachedBench
{
[STAThread]
public void Main(String args)
{
runs = 100;
start = 200;
(args.Length > 1)
{
runs = .Parse(args[0]);
start = .Parse(args[1]);
}

serverlist = { \"140.192.34.72:11211\", \"140.192.34.73:11211\" }; [Page]

// initialize the pool for memcache servers
SockIOPool pool = SockIOPool.GetInstance;
pool.SetServers(serverlist);

pool.InitConnections = 3;
pool.MinConnections = 3;
pool.MaxConnections = 5;

pool.SocketConnectTimeout = 1000;
pool.SocketTimeout = 3000;

pool.MaenanceSleep = 30;
pool.Failover = true;

pool.Nagle = false;
pool.Initialize;

MemcachedClient mc = MemcachedClient;
mc.EnableCompression = false;

keyBase = \"testKey\";
obj = \"This is a test of an object blah blah es, serialization does not seem to slow things down so much. The gzip compression is horrible horrible performance, so we _disibledevent=> for( i = start; i < start+runs; i)
{
mc.Set(keyBase + i, obj);


}
long end = DateTime.Now.Ticks;
long time = end - begin;

Console.WriteLine(runs + \" s: \" + TimeSpan(time). + \"ms\"); [Page]

begin = DateTime.Now.Ticks;
hits = 0;
misses = 0;
for( i = start; i < start+runs; i)
{
str = () mc.Get(keyBase + i);
(str != null)
hits;

misses;
}
end = DateTime.Now.Ticks;
time = end - begin;

Console.WriteLine(runs + \" gets: \" + TimeSpan(time). + \"ms\");
Console.WriteLine(\"Cache hits: \" + hits.);
Console.WriteLine(\"Cache misses: \" + misses.);

IDictionary stats = mc.Stats;
foreach( key1 in stats.Keys)
{
Console.WriteLine(key1);
Hashtable values = (Hashtable)stats[key1];
foreach( key2 in values.Keys)
{
Console.WriteLine(key2 + \":\" + values[key2]); [Page]
}
Console.WriteLine;
}

SockIOPool.GetInstance.Shutdown;
}
}
}结论通过这个对比测试我们可以看出内建Cache比使用Memcached要快出约130倍,但是从总体速度上来看Memcached并不慢这两种方式可以在项目中有选择性地结合使用可以产生很棒效果.并且Memcached可使用内存数量要多得多同时也可以做集群避免单点问题.



Tags:  分布式数据库 分布式系统 缓存同步 分布式缓存

延伸阅读

最新评论

发表评论