`
kobe学java
  • 浏览: 250459 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

如何配置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> 
   &lt;bean id="memCachedService" class="com.ms.memcached.MemCachedServiceImpl"&gt; 
    &lt;constructor-arg index="0" value="${memcached.pool.name}" /&gt; 
    &lt;constructor-arg index="1" value="${memcached.pool.servers}" /&gt; 
    &lt;constructor-arg index="2" value="${memcached.pool.initConn}" /&gt; 
    &lt;constructor-arg index="3" value="${memcached.pool.maxConn}" /&gt; 
    &lt;constructor-arg index="4" value="${memcached.pool.minConn}" /&gt; 
    &lt;constructor-arg index="5" value="${memcached.pool.socketTO}" /&gt; 
    &lt;constructor-arg index="6" value="${memcached.pool.maintSleep}" /&gt; 
    &lt;constructor-arg index="7" value="${memcached.pool.nagle}" /&gt; 
    &lt;constructor-arg index="8" value="${memcached.pool.failover}" /&gt; 
    &lt;constructor-arg index="9" value="${memcached.pool.aliveCheck}" /&gt; 
    &lt;/bean&gt; 
    </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; 
    }

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics