使用Memcached提高.net应用程序的性能

使用Memcached提高.net应用程序的性能
2011年03月27日
  如无特别说明,本博客文章为zhoufoxcn(周公)原创,任何外部引用或摘抄请注明出处,并保持内容和格式不变,未经作者同意不得用于任何盈利目的,对于非营利性转载不注明出处的保留追究法律责任的权力,谢谢合作!欢迎业内精英共同探讨交流,MSN(Email):zhoufoxcn⊙hotmail.com。
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  在应用程序运行的过程中总会有一些经常需要访问并且变化不频繁的数据,如果每次获取这些数据都需要从数据库或者外部文件系统中去读取,性能肯定会受到影响,所以通常的做法就是将这部分数据缓存起来,只要数据没有发生变化每次获取这些数据的时候直接从内存中区获取性能肯定会大大地提高。在.NET中提供了一个Cache类可以实现这些功能。在ASP.NET中可以通过HttpContext 对象的 Cache 属性或 Page 对象的 Cache 属性来获取这个类的实例。 在大部分情况下我们都可以使用Cache类来提高ASP.NET的性能,但是使用Cache类也有一些不足,比如我们不能指定Cache类所占用的内存的大小,此外在Cache中缓存的数据没有办法被另一台机器上的应用程序直接访问,因此在本文中提出另一种数据缓存方案,那就是使用分布式缓存。分布式缓存的特点是缓存的数据不必和应用程序在同一台机器上,从而大大增强了缓存数据的复用性。在本文介绍如何在.NET应用中使用Memcache作为分布式缓存。
  Memcached介绍
  Memcached 是以LiveJournal 旗下Danga Interactive 公司的Brad Fitzpatric 为首开发的一款软件。在通常的应用中我们都会将数据保存到数据库中,每次需要的时候都会从数据库去查询这些数据,如果应用程序的用户很多就会出现大量并发访问数据库的情况,这样就会增加应用程序的响应时间,使用Memcached就可以有效解决这个问题。memcached是高性能的分布式内存缓存服务器。一般的使用目的是,通过缓存数据库查询结果,减少数据库访问次数,以提高动态Web应用的速度、提高可扩展性。像大名鼎鼎的Facebook网站就使用了Memcached。周公稍后会提供Windows平台上32位和64位的Memcached程序。
  为了提高性能,Memcached中的数据都保存在Memcached内置的存储空间中。因为当Memcached重启会导致其中的数据全部丢失,所以一般的方案是将数据保存在数据库中,每次请求数据的时候先查看在Memcached有没有缓存,如果有就直接从缓存中取出数据;如果没有,就从数据库中取出数据返回给应用程序并将请求的数据缓存到Memcached中,这样一来下次请求相同的数据就可以直接从Memcached中读取而不用再去查数据库了;一旦对数据有更新,同时更新数据库和Memcached。
  Memcached是一个命令行窗口程序,可以在命令行窗口中启动也可以封装在系统服务中启动。在启动Memcached时需要提供一些必须的参数,指定Memcached运行时监听的端口和最大使用的内存大小等。如果缓存的数据大小超过指定内存,那么Memcached就会按照LRU(Least Recently Used)算法自动"删除"不使用的缓存(标记为失效),新增的缓存数据就可以使用这些标记为失效的数据所占用的内存,这样就不用担心Memcached超出所指定内存的问题。此外,为了提高性能,在缓存数据过期后Memcached并不是从物理内存中删除缓存的数据,仅仅在取出改数据的时候检查它是否已经过了有效期。
  目前有多种平台的Memcached版本,比如Linux、FreeBSD、Solaris (memcached 1.2.5以上版本)、Mac OS X及Windows平台,在Windows平台上还有32位和64位版本。
  Memcached有一套协议,利用这套协议可以对Memcached进行数据存取和查看Memcached的状态,很多程序语言都依据这套协议来操作Memcached,比如PHP、Java、C、C++及C#等。
  获取了对应平台的Memcached版本就可以运行Memcached了。在这里仅以Windows平台上的32位Memcached为例。
  运行Memcached:
  memcached.exe -p 11121 -m 64
  上面的命令是运行Memcached,指定它的监听端口是11121(这是它的默认端口,可以指定为其它大于1024的端口,因为小于1024的端口已经有了默认指定),最大使用内存为64m,如果启用了Windows防火墙,切记要在防火墙上打开这个端口。
  在调试程序时可以使用下面的命令行来运行:
  memcached.exe -p 11121 -m 64 -vv
  这样就会看到如下的结果:
  slab class 1: chunk size 88 perslab 11915
  slab class 2: chunk size 112 perslab 9362
  slab class 3: chunk size 144 perslab 7281
  slab class 4: chunk size 184 perslab 5698
  slab class 5: chunk size 232 perslab 4519
  slab class 6: chunk size 296 perslab 3542
  slab class 7: chunk size 376 perslab 2788
  slab class 8: chunk size 472 perslab 2221
  slab class 9: chunk size 592 perslab 1771
  slab class 10: chunk size 744 perslab 1409
  slab class 11: chunk size 936 perslab 1120
  slab class 12: chunk size 1176 perslab 891
  slab class 13: chunk size 1472 perslab 712
  slab class 14: chunk size 1840 perslab 569
  slab class 15: chunk size 2304 perslab 455
  slab class 16: chunk size 2880 perslab 364
  slab class 17: chunk size 3600 perslab 291
  slab class 18: chunk size 4504 perslab 232
  slab class 19: chunk size 5632 perslab 186
  slab class 20: chunk size 7040 perslab 148
  slab class 21: chunk size 8800 perslab 119
  slab class 22: chunk size 11000 perslab 95
  slab class 23: chunk size 13752 perslab 76
  slab class 24: chunk size 17192 perslab 60
  slab class 25: chunk size 21496 perslab 48
  slab class 26: chunk size 26872 perslab 39
  slab class 27: chunk size 33592 perslab 31
  slab class 28: chunk size 41992 perslab 24
  slab class 29: chunk size 52496 perslab 19
  slab class 30: chunk size 65624 perslab 15
  slab class 31: chunk size 82032 perslab 12
  slab class 32: chunk size 102544 perslab 10
  slab class 33: chunk size 128184 perslab 8
  slab class 34: chunk size 160232 perslab 6
  slab class 35: chunk size 200296 perslab 5
  slab class 36: chunk size 250376 perslab 4
  slab class 37: chunk size 312976 perslab 3
  slab class 38: chunk size 391224 perslab 2
  slab class 39: chunk size 489032 perslab 2
  
  点击"打开或关闭Windows功能"之后会看到当前系统启用的功能的状态,根据当前机器选择打开Telnet服务器端或者客户端功能,如下图所示:
  
  经过上面的操作之后就可以在客服端远程查看Memcached的状态或者操作Memcached了。下面的命令就是连接到Memcached:
  telnet localhost 11121
  连接之后会出现一个命令行窗口,在这个命令行窗口中输入"stats"就可以看到当前Memcached的状态,如下就是刚刚启动的Memcached的状态数据:
  STAT pid 852
  STAT uptime 1399
  STAT time 1300979378
  STAT version 1.2.5
  STAT pointer_size 32
  STAT curr_items 0
  STAT total_items 0
  STAT bytes 0
  STAT curr_connections 3
  STAT total_connections 5
  STAT connection_structures 4
  STAT cmd_get 0
  STAT cmd_set 0
  STAT get_hits 0
  STAT get_misses 0
  STAT evictions 0
  STAT bytes_read 23
  STAT bytes_written 415
  STAT limit_maxbytes 67108864
  STAT threads 1
  END
  通过这个数据我们就可以了解Memcached的状态了。
  这些数据所代表的意义如下:
  pid:32u,服务器进程ID。
  uptime:32u, 服务器运行时间,单位秒。
  time :32u, 服务器当前的UNIX时间。
  version :string, 服务器的版本号。
  curr_items :32u, 服务器当前存储的内容数量 Current number of items stored by the server
  total_items :32u, 服务器启动以来存储过的内容总数。
  bytes :64u, 服务器当前存储内容所占用的字节数。
  curr_connections :32u, 连接数量。
  total_connections :32u, 服务器运行以来接受的连接总数。
  connection_structures:32u, 服务器分配的连接结构的数量。
  cmd_get :32u, 取回请求总数。
  cmd_set :32u, 存储请求总数。
  get_hits :32u, 请求成功的总次数。
  get_misses :32u, 请求失败的总次数。
  bytes_read :64u, 服务器从网络读取到的总字节数。
  bytes_written :64u, 服务器向网络发送的总字节数。
  limit_maxbytes :32u, 服务器在存储时被允许使用的字节总数。
  上面的描述中32u和64u表示32位和64位无符号整数,string表示是string类型数据。
  在.NET中应用Memcached
  有很多.NET版本的Memcached客户端程序,在这里周公使用的Enyim Memcached,可以到https://github.com/enyim/EnyimMemcached/下载最新的版本。
  要想在项目中使用Memcached,需要添加对Enyim.Caching.dll的应用。除此之外,我们可能还需要在config文件中配置Memcached的信息(也可以在程序代码中指定,但那样不灵活),如下就是一个config文件配置的例子: --> 如果我们配置了多个Memcached的实例,可以想上面的注释部分那样在节点下添加多个Memcached的实例配置。
  这里需要说明的是如果我们需要向Memcached中添加自定义数据类型时,我们需要将该数据类型添加上[Serializable]标记。
  下面是一个Enyim Memcached的例子: using System; using System.Collections.Generic; using System.Linq; using System.Text; using Enyim.Caching; using Enyim.Caching.Memcached; /* * 作者:周公(zhoufoxcn) * 日期:2011-03-24 * 原文出处:http://blog.csdn.net/zhoufoxcn 或http://zhoufoxcn.blog.51cto.com * 版权说明:本文可以在保留原文出处的情况下使用于非商业用途,周公对此不作任何担保或承诺。 * */ namespace MemcachedMonitor { [Serializable] public class Person { public int UserId { get; set; } public string UserName { get; set; } } public class MemcachedDemo { private static MemcachedClient client = new MemcachedClient("enyim.com/memcached"); public void SetDemo() { Person person = new Person { UserId = 1, UserName = "李刚" }; //不带过期时间的存储,Memcached将根据LRU来决定过期策略 bool success=client.Store(StoreMode.Add, person.UserName, person); //带过期时间的缓存 //bool success = client.Store(StoreMode.Add, person.UserName, person, DateTime.Now.AddMinutes(10)); Console.WriteLine("存储[{0}]的结果:{1}", person.UserName, success); } public void GetDemo() { Person person = client.Get("李刚"); if (person != null) { Console.WriteLine("取回[{0}]的结果--UserId:{1},UserName:{2}", "李刚", person.UserId, person.UserName); } else { Console.WriteLine("取回[{0}]失败!", "李刚"); } } public void MultiGetDemo() { List personNameList = new List(); for (int i = 0; i 中的指定的所有数据 IDictionary resultList = client.Get(personNameList); Person person; foreach (KeyValuePair item in resultList) { person = item.Value as Person; if (person != null) { Console.WriteLine("取回[{0}]的结果--UserId:{1},UserName:{2}", "李刚", person.UserId, person.UserName); } else { Console.WriteLine("取回[{0}]失败!", "李刚"); } } } } } 说明:如果需要一次从Memcached中取回多个缓存的数据,可以参考MultiGetDemo()方法,这样一来只需要一次网络通讯就可以取回全部数据,减少网络连接时间。此外,在Memcached客户端可以使用Text或者Binary协议,经过周公千万次测试比较,使用Binary协议性能略高于使用Text协议。在上面的config文件中周公就配置使用了Binary协议。
  总结,使用Memcached这样的分布式缓存可以大大提高应用程序的性能,经过周公测试,正确使用Memcached可以将单台服务器的并发访问数从20提高到1000左右,也就是提高了50倍,这是一个相当客观的提升!限于篇幅,关于Memcached的更深更详细的用法没有在本篇介绍,此文算作抛砖引玉,读者可以自行参考其它相关资料。
  周公
  2011-03-25
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值