Memcache 是什么?
Memcached是由Danga Interactive开发的,高性能的,分布式的内存对象缓存系统,用于在动态应用中减少数据库负载,提升访问速度。
Memcache最早是为 LiveJournal 服务的,使用这个缓存项目来构建自己大负载的网站,来分担数据库的压力。
它可以应对任意多个连接,使用非阻塞的网络 IO 。由于它的工作机制是在内存中开辟一块空间,然后建立一个 HashTable , Memcached 自管理这些 HashTable 。
Memcache是高性能的分布式内存缓存服务器。 一般的使用目的是,通过缓存数据库查询结果,减少数据库访问次数,以提高动态Web应用的速度、 提高可扩展性。
Memcache 工作原理
首先 memcached 是以守护程序方式运行于一个或多个服务器中,随时接受客户端的连接操作,客户端可以由各种语言编写,目前已知的客户端 API 包括 Perl/PHP/Python/Ruby/Java/C#/C 等等。客户端在与memcached 服务建立连接之后,接下来的事情就是存取对象了,每个被存取的对象都有一个唯一的标识符key ,存取操作均通过这个 key 进行,保存到 memcached 中的对象实际上是放置内存中的,并不是保存在cache 文件中的,这也是为什么 memcached 能够如此高效快速的原因。注意,这些对象并不是持久的,服务停止之后,里边的数据就会丢失。
与许多 cache 工具类似, Memcached 的原理并不复杂。它采用了 C/S 的模式,在 server 端启动服务进程,在启动时可以指定监听的 ip ,自己的端口号,所使用的内存大小等几个关键参数。一旦启动,服务就一直处于可用状态。Memcached 的目前版本是通过 C 实现,采用了单进程,单线程,异步 I/O ,基于事件 (event_based) 的服务方式 . 使用libevent 作为事件通知实现。多个 Server 可以协同工作,但这些 Server 之间是没有任何通讯联系的,每个 Server 只是对自己的数据进行管理。
Client 端通过指定 Server 端的 ip 地址 ( 通过域名应该也可以 ) 。需要缓存的对象或数据是以 key->value 对的形式保存在 Server 端。 key 的值通过 hash 进行转换,根据 hash 值把 value 传递到对应的具体的某个 Server上。当需要获取对象数据时,也根据 key 进行。首先对 key 进行 hash ,通过获得的值可以确定它被保存在了哪台 Server上,然后再向该 Server 发出请求。 Client 端只需要知道保存 hash(key) 的值在哪台服务器上就可以了。
其实说到底, memcache 的工作就是在专门的机器的内存里维护一张巨大的 hash 表,来存储经常被读写的一些数组与文件,从而极大的提高网站的运行效率。
Memcached的使用
一 、Memcached服务器端的安装 (此处将其作为系统服务安装)
下载文件:memcached 1.2.1 for Win32 binaries (Dec 23, 2006)
1 解压缩文件到c:\memcached
2 命令行输入 'c:\memcached\memcached.exe -d install'
3 命令行输入 'c:\memcached\memcached.exe -d start' ,该命令启动 Memcached ,默认监听端口为 11211
通过 memcached.exe -h 可以查看其帮助
ps:安装时报错误的话,如果是WIN7系统,那么用管理员身份进入CMD模式,找到CMD.EXE,用右键选择管理员模式进入就可以了。
memcached.exe -p 11211 -m 64m -vv
-p | 使用的TCP端口。默认为11211 |
-m | 最大内存大小。默认为64M |
-vv | 用very vrebose模式启动,调试信息和错误输出到控制台 |
-d | 作为daemon在后台启动 |
-d restart 重启memcached服务
-d stop|shutdown 关闭正在运行的memcached服务
-M 内存耗尽时返回错误,而不是删除项
-c 最大同事连接数,默认是1024
-f 块大小增长因子,默认是1.25
-n 最小分配空间 key+value+flags默认是48
-h 显示帮助
二、客户端使用
下载memcached java client:http://www.whalin.com/memcached/#download
1 解压后将java_memcached-release_2.0.1.jar jar包添加到工程的classpath中
2 利用memcached java client 一个简单的应用
| public class TestMemberCache { |
| protected static MemCachedClient mcc = new MemCachedClient(); |
| String[] servers = { "127.0.0.1:11211" }; |
| Integer[] weights = { 3 }; |
| SockIOPool pool = SockIOPool.getInstance(); |
| pool.setServers(servers); |
| pool.setWeights(weights); |
| pool.setMaxIdle( 1000 * 60 * 60 * 6 ); |
| pool.setSocketConnectTO( 0 ); |
| mcc.setCompressEnable( true ); |
| mcc.setCompressThreshold( 64 * 1024 ); |
| public static void bulidCache() { |
| mcc.set( "test" , "This is a test String" , new Date( 10000 )); |
| mcc.set( "test" , "This is a test String111" , new Date( 10000 )); |
| User u1 = (User) mcc.get( "user" ); |
| System.out.println(u1.getUsername()); |
| public static void output() { |
| String value = (String) mcc.get( "test" ); |
| System.out.println(value); |
| public static void main(String[] args) { |
输出结果为:
aaaa
This is a test String111
MemberCache及其他缓存等相关知识:
1)JBOSS CACHE, EHCACHE, 等JAVA写成的CACHE,一般都是和主程序在同一机器上,内存直接访问,比memcached要快。但如果有多个server,每个server都有 自己的一份cache,要采用一些notification or replicate机制才能synchronize。而且,cache size受制于heap size setting。memcached 运行在主程序以外的机器上,通过网络访问来传递数据。因为是专门的server,所以size不受限制。如果cache data 不大(300MB以下?),无须用memcached.
2)memcached组成它的n台机器里有一个down了,并不会整个挂掉,只会访问某些cache内容无法命中,就算全部挂掉,Cache就是减少对数据库访问的,所以无非就是对数据库压力大一些而已,如果希望Cache持久化,或者带有故障切换功能,可以用memcachedb。
3)Cache Server的可靠性比DB Server还要高
4)memcached 要求set的对象必须是可序列化对象,jboss cache等java obect cache是没有这个说法的,这是本质的不同的,但是他可以在网络上用,所以必须序列化也可理解
5)memcached 并发连接可以上到1w,我手头的应用常常保持在3-5k;它的快不仅是因为用了libevent,还因为它采取了“用内存冗余换存取速度”的内存管理策 略,网上有文章专门分析它的内存分配回收管理的源码,讲的很清楚,在这上面jboss cache、ehcache、oscache跟它没法比;memcached的集群也非常好,听说国外有200+的memcached集群,我们也有这方 面的尝试,效果也很好,一台down掉根本不会引起其他机器down掉,只是这台的数据丢了,需要慢慢积累回来;而且支持多客户端,java、php、 python、ruby可以共享数据,就把它当作数据库用。
我的建议是:你的应用访问量比较大,对响应速度要求很高,对数据一致性要求一般时,用它,挡在数据库前面,非常爽(memcached是互联网公司开发的,正好满足这三个条件);如果应用不忙,用用ehcache就行了。
6)ehcache、oscache 的数据都是在本机服务器上的,访问时走的仅是系统总线。而memcached走的是网络。关于传输速度来讲我们的应用读取memcached的网络流量是每秒有2MB的流量,是读取数据库的网络流量的大约5倍。但是你要知道现在随便的PC机都是千兆网卡,因此 memcached的get/set操作的延时非常少,并不比echache的get/set慢多少。在一个完整的web应用当中,我的压力测试表明,性 能差异 <= 5%
7)论坛、sns这样的应用,会使用多种技术进行缓存。
拿sohu的bbs来说吧,pv为5000w,峰值8000w
其中帖子、评论读写频繁,其他部分读频繁。
帖子列表、评论列表使用c开发(其中排序算法很巧妙),socket调用
帖子、评论内容使用squid缓存
其他读频繁的部分使用memcached、squid、定时生成静态页面等多种技术。
数据库用mysql,分表。
个人认为,小规模应用中,jvm级别的cache可以用用,memcached可用可不用
大规模网站应用,肯定是系统水平切分,多种cache结合。
8)memcached非常快,但我没说过比本机的ehcache还快,但用本地缓存有两点不爽:
1.缓存放在内存or放在磁盘?应用重启会导致内存缓存丢失,放在磁盘又不够快。内存开多大合适?如果是大访问量应用,缓存对象集中淘汰可能引起服务器load急剧波动(我们吃过亏,现在也开ehcache,但缓存对象的上限开的很小)
2.集群应用里缓存对象如何共享?jboss cache用的是广播,访问量大的时候,可以把你的服务拖死,这个我们也吃过亏
当然,有人谈到了sohu的例子,一旦访问量大了,各种缓存都得用着,目前我们就是squid + memcached + ehcache。squid也是好东西,但缓存内容删除不太灵活,比较适合web1.0,比如新浪搜狐的新闻
另外,java memcached client用1.6好了,没必要升级到2.1,2.X似乎还不太稳定。