Memcached学习笔记
以前写的一个关于Memcached的东东,希望对大家了解Memcached有帮助 本周研究了一下memcached缓存机制,总结一下。 在数据驱动的web开发中,经常要重复从数据库中取出相同的数据,这种重复极大的增加了数据库负载。缓存是解决这个问题的好办法。 Memcached是由Danga Interactive开发的,高性能的,分布式的内存对象缓存系统,用于在动态应用中减少数据库负载,提升访问速度。 通过在内存里维护一个统一的巨大的hash表,Memcached能够用来存储各种格式的数据,包括图像、视频、文件以及数据库检索的结果等。 Memcached使用了libevent(如果可以的话,在linux下使用epoll)来均衡任何数量的打开链接,使用非阻塞的网络I/O,对内部对象实现引用计数(因此,针对多样的客户端,对象可以处在多样的状态), 使用自己的页块分配器和哈希表, 因此虚拟内存不会产生碎片并且虚拟内存分配的时间复杂度可以保证为O(1).。 Danga Interactive为提升Danga Interactive的速度研发了Memcached。目前,LiveJournal.com每天已经在向一百万用户提供多达两千万次的页面访问。而这些,是由一个由web服务器和数据库服务器组成的集群完成的。Memcached几乎完全放弃了任何数据都从数据库读取的方式,同时,它还缩短了用户查看页面的速度、更好的资源分配方式,以及Memcache失效时对数据库的访问速度。 Memcached的特点 Memcached的缓存是一种分布式的,可以让不同主机上的多个用户同时访问, 因此解决了共享内存只能单机应用的局限,更不会出现使用数据库做类似事情的时候,磁盘开销和阻塞的发生。memcached作为高速运行的分布式缓存服务器,具有以下的特点。 ? 协议简单 ? 基于libevent的事件处理 ? 内置内存存储方式 ? memcached不互相通信的分布式 memcached尽管是“分布式”缓存服务器,但服务器端并没有分布式功能。各个memcached不会互相通信以共享信息。那么,怎样进行分布式呢?这完全取决于客户端的实现。本连载也将介绍memcached的分布式。 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 可以查看其帮助 二、客户端使用 下载memcached java client:http://www.whalin.com/memcached/#download 1 解压后将java_memcached-release_2.0.1.jar jar包添加到工程的classpath中 2 利用memcached java client 一个简单的应用 Java代码 package com.icafe.test; imp imp imp
public class Test { protected static MemCachedClient mcc = new MemCachedClient();
static { //这里server是一个数组,就是说可能有多个memcached server String[] servers ={"127.0.0.1:11212"}; //weithts也是一个数组,和server相对应,权重值 Integer[] weights = { 3 };
//创建一个实例对象SockIOPool SockIOPool pool = SockIOPool.getInstance();
// set the servers and the weights //设置Memcached Server pool.setServers( servers ); pool.setWeights( weights );
// set some basic pool settings // 5 initial, 5 min, and 250 max conns // and set the max idle time for a conn // to 6 hours pool.setInitConn( 5 ); pool.setMinConn( 5 ); pool.setMaxConn( 250 ); pool.setMaxIdle( 1000 * 60 * 60 * 6 );
// set the sleep for the maint thread // it will wake up every x seconds and // maintain the pool size pool.setMaintSleep( 30 );
// Tcp的规则就是在发送一个包之前,本地机器会等待远程主机 // 对上一次发送的包的确认信息到来;这个方法就可以关闭套接字的缓存, // 以至这个包准备好了就发; pool.setNagle( false ); //连接建立后对超时的控制 pool.setSocketTO( 3000 ); //连接建立时对超时的控制 pool.setSocketConnectTO( 0 );
// initialize the connection pool //初始化一些值并与MemcachedServer段建立连接 pool.initialize();
// lets set some compression on for the client // compress anything larger than 64k mcc.setCompressEnable( true ); mcc.setCompressThreshold( 64 * 1024 ); }
public static void bulidCache(){ //set(key,value,Date) ,Date是一个过期时间,如果想让这个过期时间生效的话,这里传递的new Date(long date) 中参数date,需要是个大于或等于1000的值。 //因为java client的实现源码里是这样实现的 expiry.getTime() / 1000 ,也就是说,如果 小于1000的值,除以1000以后都是0,即永不过期 mcc.set( "test", "This is a test String" ,new Date(11211)); //十秒后过期
}
public static void output() { //从cache里取值 String value = (String) mcc.get( "test" ); System.out.println(value); }
public static void main(String[] args){ bulidCache(); output();
}
} 还可以把memcached的相关配置写到SPRING配置文件里,写法如下: <bean id="memcache" class="com.danga.MemCached.SockIOPool" factory-method="getInstance" init-method="initialize" destroy-method="shutDown"> <constructor-arg> <value>memcache</value> </constructor-arg> <property name="servers"> <list> <value>${memcache.server1}</value> <value>${memcache.server2}</value> … </list> </property> <property name="initConn"> <value>${memcache.initConn}</value> </property> <property name="minConn"> <value>${memcache.minConn}</value> </property> <property name="maxConn"> <value>${memcache.maxConn}</value> </property> <property name="maintSleep"> <value>${memcache.maintSleep}</value> </property> <property name="nagle"> <value>${memcache.nagle}</value> </property> <property name="socketTO"> <value>${memcache.socketTO}</value> </property> </bean> 配置信息 memcache.server=192.168.0.1:11211 memcache.server=192.168.0.2:11211 … memcache.initConn=20 memcache.minConn=10 memcache.maxConn=50 memcache.maintSleep=30 memcache.nagle=false memcache.socketTO=3000 memcached常用方法: 1、设置数据到内存 memCachedClient.set(key, value, cache中存在时长); 2、删除内存中的数据 memCachedClient.delete(key); 3、取得内存中的数据 memCachedClient.get(key); 封装好的MemcachedManager.java MemCachedClient mc;
public CacheService(){ mc = new MemCachedClient(); mc.setCompressEnable(false); } /** * 放入 */ public void put(String key, Object obj) { Assert.hasText(key); Assert.notNull(obj); Assert.notNull(localCache); if (this.cacheCluster) { mc.set(key, obj); } else { Element element = new Element(key, (Serializable) obj); localCache.put(element); } } /** * 删除 */ public void remove(String key){ Assert.hasText(key); Assert.notNull(localCache); if (this.cacheCluster) { mc.delete(key); }else{ localCache.remove(key); } } /** * 得到 */ public Object get(String key) { Assert.hasText(key); Assert.notNull(localCache); Object rt = null; if (this.cacheCluster) { rt = mc.get(key); } else { Element element = null; try { element = localCache.get(key); } catch (CacheException cacheException) { throw new DataRetrievalFailureException("Cache failure: " + cacheException.getMessage()); } if(element != null) rt = element.getValue(); } return rt; } /** * 判断是否存在 * */ public boolean exist(String key){ Assert.hasText(key); Assert.notNull(localCache); if (this.cacheCluster) { return mc.keyExists(key); }else{ return this.localCache.isKeyInCache(key); } } private void init() { if (this.cacheCluster) { String[] serverlist = cacheServerList.split(","); Integer[] weights = this.split(cacheServerWeights); // initialize the pool for memcache servers SockIOPool pool = SockIOPool.getInstance(); pool.setServers(serverlist); pool.setWeights(weights); pool.setInitConn(initialConnections); pool.setMinConn(minSpareConnections); pool.setMaxConn(maxSpareConnections); pool.setMaxIdle(maxIdleTime); pool.setMaxBusyTime(maxBusyTime); pool.setMaintSleep(maintThreadSleep); pool.setSocketTO(socketTimeOut); pool.setSocketConnectTO(socketConnectTO); pool.setNagle(nagleAlg); pool.setHashingAlg(SockIOPool.NEW_COMPAT_HASH); pool.initialize(); logger.info("初始化memcached pool!"); } }
private void destory() { if (this.cacheCluster) { SockIOPool.getInstance().shutDown(); } } } |