如何配置Memcached服务器(转载)
Memcached是高性能的,分布式的内存对象缓存系统,用于在动态应用中减少数据库负载,提升访问速度。Memcached由Danga Interactive(运营LiveJournal的技术团队)开发,用于提升LiveJournal.com访问速度的。? LJ每秒动态页面访问量是几千次,用户700万。Memcached将数据负载大幅度降低,更好的分配资源,更快速访问。?
??????? 其实Memcache是这个项目的名称,而memcached是它服务器端的主程序文件名?
??????? Memcached可以应对任意多个连接,使用非阻塞的网络IO。由于它的工作机制是在内存中开辟一块空间,然后建立一个HashTable,Memcached自管理这些HashTable.?
??????? 虽然memcached使用了同样的“Key=>Value”方式组织数据,但是它和共享内存、APC等本地缓存有非常大的区别。 Memcached是分布式的,也就是说它不是本地的。它基于网络连接(当然它也可以使用localhost)方式完成服务,本身它是一个独立于应用的程 序或守护进程(Daemon方式)。?
??????? Memcached最吸引人的一个特性就是支持分布式部署;也就是说可以在一群机器上建立一堆 Memcached 服务,每个服务可以根据具体服务器的硬件配置使用不同大小的内存块,这样一来,理论上可以建立一个无限巨大的基于内存的cache storage 系统。?
??????? Memcached使用libevent库实现网络连接服务,理论上可以处理无限多的连接,但是它和Apache不同,它更多的时候是面向稳定的持续连接 的,所以它实际的并发能力是有限制的。在保守情况下memcached的最大同时连接数为200,这和Linux线程能力有关系,这个数值是可以调整的。 关于libevent可以参考相关文档。 Memcached内存使用方式也和APC不同。APC是基于共享内存和MMAP的,memcachd有自己的内存分配算法和管理方式,它和共享内存没有 关系,也没有共享内存的限制,通常情况下,每个memcached进程可以管理2GB的内存空间,如果需要更多的空间,可以增加进程数。?
??????? Memcached在很多时候都是作为数据库前端cache使用的。因为它比数据库少了很多SQL解析、磁盘操作等开销,而且它是使用内存来管理数据的, 所以它可以提供比直接读取数据库更好的性能,在大型系统中,访问同样的数据是很频繁的,memcached可以大大降低数据库压力,使系统执行效率提升。 另外,memcached也经常作为服务器之间数据共享的存储媒介,例如在SSO系统中保存系统单点登陆状态的数据就可以保存在memcached中,被 多个应用共享。?
??????? 需要注意的是,使用Memcache的网站一般流量都是比较大的,为了缓解数据库的压力,让Memcache作为一个缓存区域,把部分信息保存在内存中, 在前端能够迅速的进行存取。由于memcached使用内存管理数据,所以它是易失的,当服务器重启,或者memcached进程中止,数据便会丢失,所 以memcached不能用来持久保存数据。很多人的错误理解,memcached的性能非常好,好到了内存和硬盘的对比程度,其实memcached使 用内存并不会得到成百上千的读写速度提高,它的实际瓶颈在于网络连接,它和使用磁盘的数据库系统相比,好处在于它本身非常“轻”,因为没有过多的开销和直 接的读写方式,它可以轻松应付非常大的数据交换量,所以经常会出现两条千兆网络带宽都满负荷了,memcached进程本身并不占用多少CPU资源的情 况。?
?????? Memcached是“分布式”的内存对象缓存系统,所以那些不需要“分布”的,不需要共享的,或者干脆规模小到只有一台服务器的应用,memcached不会带来任何好处,相反还会拖慢系统效率,因为网络连接同样需要资源,即使是UNIX本地连接也一样。?
Windows下的Memcache安装?
1. 下载memcache的windows稳定版,解压放某个盘下面,比如在c:\memcached?
2. 在终端(也即cmd命令界面)下输入 c:\memcached\memcached.exe -d install??????????? --安装memcached成为服务,这样才能正常运行,否则运行失败!?
3. 再输入: c:\memcached\memcached.exe -d start??? --启动memcached的。?
????
????? 以后memcached将作为windows的一个服务每次开机时自动启动。这样服务器端已经安装完毕了。?
Linux下的安装:?
1.下载memcached和libevent,放到 /tmp 目录下?
# cd /tmp?
# wget http://www.danga.com/memcached/dist/memcached-1.2.0.tar.gz?
# wget http://www.monkey.org/~provos/libevent-1.2.tar.gz?
2.先安装libevent:?
# tar zxvf libevent-1.2.tar.gz?
# cd libevent-1.2?
# ./configure –prefix=/usr?
# make?
# make install?
3.测试libevent是否安装成功:?
# ls -al /usr/lib | grep libevent?
lrwxrwxrwx 1 root root 21 11?? 12 17:38 libevent-1.2.so.1 -> libevent-1.2.so.1.0.3?
-rwxr-xr-x 1 root root 263546 11?? 12 17:38 libevent-1.2.so.1.0.3?
-rw-r–r– 1 root root 454156 11?? 12 17:38 libevent.a?
-rwxr-xr-x 1 root root 811 11?? 12 17:38 libevent.la?
lrwxrwxrwx 1 root root 21 11?? 12 17:38 libevent.so -> libevent-1.2.so.1.0.3?
4.安装memcached,同时需要安装中指定libevent的安装位置:?
# cd /tmp?
# tar zxvf memcached-1.2.0.tar.gz?
# cd memcached-1.2.0?
# ./configure –with-libevent=/usr?
# make?
# make install?
如果中间出现报错,请仔细检查错误信息,按照错误信息来配置或者增加相应的库或者路径。?
安装完成后会把memcached放到 /usr/local/bin/memcached ,?
5.测试是否成功安装memcached:?
# ls -al /usr/local/bin/mem*?
-rwxr-xr-x 1 root root 137986 11?? 12 17:39 /usr/local/bin/memcached?
-rwxr-xr-x 1 root root 140179 11?? 12 17:39 /usr/local/bin/memcached-debug?
memcached的基本设置:?
1.启动Memcache的服务器端:?
# /usr/local/bin/memcached -d -m 10 -u root -l 192.168.0.200 -p 12000 -c 256 -P /tmp/memcached.pid?
-d选项是启动一个守护进程,?
-m是分配给Memcache使用的内存数量,单位是MB,这里是10MB,?
-u是运行Memcache的用户,这里是root,?
-l是监听的服务器IP地址,如果有多个地址的话,这里指定了服务器的IP地址192.168.0.200,?
-p是设置Memcache监听的端口,这里设置了12000,最好是1024以上的端口,?
-c选项是最大运行的并发连接数,默认是1024,这里设置了256,按照你服务器的负载量来设定,?
-P是设置保存Memcache的pid文件,这里是保存在 /tmp/memcached.pid,?
2.如果要结束Memcache进程,执行:?
# kill `cat /tmp/memcached.pid`?
也可以启动多个守护进程,不过端口不能重复。?
3.重启apache,service httpd restart?
java的客户端连接程序:?
?????? 将java_memcached-release_1.6.zip解压后的目录中的java_memcached-release_2.0.jar文件复制到java项目的lib目录下。?
package utils.cache;?
import java.util.Date;?
import com.danga.MemCached.MemCachedClient;?
import com.danga.MemCached.SockIOPool;?
/**?
* 使用memcached的缓存实用类.?
*/?
public class MemCached?
{?
??? // 创建全局的唯一实例?
??? protected static MemCachedClient? mcc =? new MemCachedClient();?
????
??? protected static MemCached memCached = new MemCached();?
????
??? // 设置与缓存服务器的连接池?
??? static {?
??????? // 服务器列表和其权重?
??????? String[] servers = {"127.0.0.1:11211"};?
??????? Integer[] weights = {3};?
??????? // 获取socke连接池的实例对象?
??????? SockIOPool? sockIOPool = SockIOPool.getInstance();?
??????? // 设置服务器信息?
??????? sockIOPool.setServers( servers );?
??????? sockIOPool.setWeights( weights );?
??????? // 设置初始连接数、最小和最大连接数以及最大处理时间?
??????? sockIOPool.setInitConn( 5 );?
??????? sockIOPool.setMinConn( 5 );?
??????? sockIOPool.setMaxConn( 250 );?
??????? sockIOPool.setMaxIdle( 1000 * 60 * 60 * 6 );?
??????? // 设置主线程的睡眠时间?
??????? sockIOPool.setMaintSleep( 30 );?
??????? // 设置TCP的参数,连接超时等?
??????? sockIOPool.setNagle( false );?
??????? sockIOPool.setSocketTO( 3000 );?
??????? sockIOPool.setSocketConnectTO( 0 );?
??????? //sockIOPool.setFailover(bFailover);?
??????? //sockIOPool.setAliveCheck(bAliveCheck);?
??????? // 初始化连接池?
??????? sockIOPool.initialize();?
??????? // 压缩设置,超过指定大小(单位为K)的数据都会被压缩?????
??????? if (memCachedClient == null)?
??????? {?
??????????? mcc = new MemCachedClient(sPoolName);?
??????????? mcc.setCompressEnable(true);?
??????????? mcc.setCompressThreshold(4096);?
??????????? mcc.setPrimitiveAsString(true);?
??????? }?
??? }?
/*?
<h3>基于Spring的配置,如下:</h3>?
? <pre>?
?? <bean id="memCachedService" value="${memcached.pool.name}" />?
??? <constructor-arg index="1" value="${memcached.pool.servers}" />?
??? <constructor-arg index="2" value="${memcached.pool.initConn}" />?
??? <constructor-arg index="3" value="${memcached.pool.maxConn}" />?
??? <constructor-arg index="4" value="${memcached.pool.minConn}" />?
??? <constructor-arg index="5" value="${memcached.pool.socketTO}" />?
??? <constructor-arg index="6" value="${memcached.pool.maintSleep}" />?
??? <constructor-arg index="7" value="${memcached.pool.nagle}" />?
??? <constructor-arg index="8" value="${memcached.pool.failover}" />?
??? <constructor-arg index="9" value="${memcached.pool.aliveCheck}" />?
??? </bean>?
??? </pre>?
??? <h3>利用com.MS.cache.properties来设置参数,如下:</h3>?
??? <pre>?
??? memcached.pool.name = MS?
??? memcached.pool.servers = 192.168.9.132:12000,192.168.9.133:12000?
??? memcached.pool.initConn = 128?
??? memcached.pool.maxConn = 1024?
??? memcached.pool.minConn = 20?
??? memcached.pool.socketTO = 3000?
??? memcached.pool.maintSleep = 30?
??? memcached.pool.nagle = false?
??? memcached.pool.failover = true?
??? memcached.pool.aliveCheck = true?
??? </pre>?
*/?
??
??? /**?
???? * 保护型构造方法,不允许实例化!?
???? */?
??? protected MemCached()?
??? {?
????????
??? }?
????
??? /**?
???? * 获取唯一实例.?
???? */?
??? public static MemCached getInstance()?
??? {?
??????? return memCached;?
??? }?
????
??? /**?
???? * 添加一个指定的值到缓存中.?
???? * @param key?
???? * @param value?
???? */?
??? //新增指定key的缓存内容,但不覆盖已存在的内容。?
??? public boolean add(String key, Object value)?
??? {?
??????? return mcc.add(key, value);?
??? }?
??
?? //expiry过期时间?
??? public boolean add(String key, Object value, Date expiry)?
??? {?
??????? return mcc.add(key, value, expiry);?
??? }?
??
??? //新增或覆盖指定Key的缓存内容?
??? public boolean set(String key, Object value)?
??? {?
??????? return mcc.set(key, value);?
??? }?
??
??? //lExpiry过期时间?
??? public boolean set(String key, Object value, long lExpiry)?
??? {?
??????? return mcc.set(key, value, new Date(lExpiry));?
??? }?
??
?? //根据指定的Key获取缓存内容?
??? public boolean get(String key)?
??? {?
??????? return mcc.get(key);?
??? }?
??? //根据指定Key更新缓存内容?
??? public boolean replace(String key, Object value)?
??? {?
??????? return mcc.replace(key, value);?
??? }?
??
??? //lExpiry 指定的时间?
??? public boolean replace(String key, Object value, long lExpiry)?
??? {?
??????? return mcc.replace(key, value, new Date(lExpiry));?
??? }?
???? //根据指定Key删除缓存内容?
??? public boolean delete(String key, Object value)?
??? {?
??????? return mcc.delete(key, value);?
??? }?
??? //根据指定Key在指定时间后删除缓存内容?
???? public boolean delete(String key, Object value, long lExpiry)?
??? {?
??????? return mcc.delete(key, value, new Date(lExpiry));?
??? }?
??
??? //检测Cache中当前Key是否存在?
???? public boolean exists(String key)?
??? {?
??????? return mcc.exists(key);?
??? }?
?? //根据指定一批Key批量获取缓存内容。?
?? /*?
?? * @param sKeys 指定的一批Key。?
?? * @return Object[oValue]?
?? */?
??? public Object[] getMultiArray(String[] sKeys) throws ServiceException?
?? {?
?????? return memCachedClient.getMultiArray(sKeys);?
?? }?
?? /**?
?? * 根据指定一批Key批量获取缓存内容。?
?? *?
?? * @param sKeys 指定的一批Key。?
?? * @return Map<sKey, oValue>?
?? */?
??? public Map<String, Object> getMulti(String[] sKeys) throws ServiceException?
?? {?
?????? return memCachedClient.getMulti(sKeys);?
?? }?
????????
??? public static void main(String[] args)?
??? {?
??????? MemCached memCached= MemCached.getInstance();?
??????? memCached.add("hello", 234);?
??????? System.out.print("get value : " + memCached.get("hello"));?
??? }?
}?
??? 那么我们就可以通过简单的像main方法中操作的一样存入一个变量,然后再取出进行查看,我们可以看到先调用了add,然后再进行get,我们运行一次 后,234这个值已经被我们存入了memcached的缓存中的了,我们将main方法中红色的那一行注释掉后,我们再运行还是可以看到get到的 value也是234,即缓存中我们已经存在了数据了。?
??? 对基本的数据我们可以操作,对于普通的POJO而言,如果要进行存储的话,那么比如让其实现java.io.Serializable接口,因为 memcached是一个分布式的缓存服务器,多台服务器间进行数据共享需要将对象序列化的,所以必须实现该接口,否则会报错的。?
Entity?
/**?
? * 获取当前实体的缓存Id?
? *?
? * @return?
? */?
public String getCacheId()?
{?
? return getCacheId(this.getClass(), sBreedId);?
}?
get?
? public Breed getBreedById(String sBreedId) throws ServiceException?
? {?
???? Breed breed = (Breed)memCachedService.get(getCacheId(Breed.class, sBreedId));?
??
???? if(breed == null)?
???? {?
??????? breed = service.get("breed.getBreedById", sBreedId);?
???
??????? if(breed != null)?
??????? {?
?????????? memCachedService.set(breed.getBreedId(), breed);?
??????? }?
???? }?
??
???? return breed;?
? }??
save?
?? memCachedService.set(spider.getCacheId(), breed);?
update?
?? memCachedService.replace(spider.getCacheId(), breed);?
remove?
?? memCachedService.delete(getCacheId(Spider.class, IbreedId));?
或?
?? memCachedService.delete(breed.getCacheId());?
listAll?
?? public List listAll() throws ServiceException?
?? {?
????? List breeds = new ArrayList ();?
??
????? List breedIds = (List)memCachedService.get(getKeyByMap("Breed", null));?
??
????? if(ObjectUtils.isEmpty(breedIds))?
????? {?
???????? breeds = service.list("breed.getAllBreed", null);?
???
???????? if (!ObjectUtils.isEmpty(breeds))?
???????? {?
??????????? breedIds = new ArrayList();?
????
??????????? for (Breed breed : breeds)?
??????????? {?
??????????????? breedIds.add(breed.getBreedId());?
??????????? }?
????
??????????? memCachedService.set(getKeyByMap("Breed", null), breedIds);?
???????? }?
????? }?
????? else?
????? {?
?????????? for (String sBreedId : breedIds)?
?????????? {?
?????????????? Breed breed = getBreedById(sBreedId);?
????
?????????????? if (breed != null)?
?????????????? {?
????????????????? breeds.add(breed);?
?????????????? }?
?????????? }?
????? }?
??
????? return breeds;?
??? }