xmemcached发布1.0-BETA版

    xiaoxiao2024-01-18  168

    xmemcached发布 1.0-beta,从0.60直接到1.0-beta,主要改进如下: 1、支持更多协议,在已有协议支持的基础上添加了append、prepend、gets、批量gets、cas协议的支持,具体请查看XMemcachedClient类的实例方法。重点是cas操作,下文将详细描述下。 2、memcached分布支持,支持连接多个memcached server,支持简单的余数分布和一致性哈希分布。 3、0.60版本以来的bug修复。    memcached 1.2.4之后开始支持cas协议,该协议存储数据同时发送一个版本号,只有当这个版本号与memcached server上该key的最新版本一致时才更新成功,否则返回EXISTS,版本号的获取需要通过gets协议获得,cas全称就是compare and set,如果对hibernate乐观锁和java.util.concurrent.atomic包都比较熟悉的话这个概念应该很了解了。xmemcached 1.0-beta开始支持cas协议,看例子: XMemcachedClient client  =   new  XMemcachedClient(); client.addServer( " localhost " , 11211 ); client.set( " a " 0 1 );  // 设置a为1 GetsResponse result  =  client.gets( " a " ); long  cas  =  result.getCas();  // 获取当前cas // 尝试更新a成2 if  ( ! client.cas( " a " 0 2 , cas))      System.err.println( " cas error " );     XMemcachedClient.cas(final String key, final int exp, Object value, long cas)将尝试更新key的值到value,如果失败就返回false。这样搞好像很麻烦,需要先gets获取cas值,然后再调用cas方法更新,因此XMemcached提供了一个包装类可以帮你搞定这两步,并且提供重试机制:              /**              * 合并gets和cas,利用CASOperation               */             client.cas( " a " 0 new  CASOperation() {                 @Override                  public   int  getMaxTries() {                      return   10 ;                 }                 @Override                  public  Object getNewValue( long  currentCAS, Object currentValue) {                     System.out.println( " current value  "   +  currentValue);                      return   2 ;                 }             });     通过 CASOperation,你只要实现两个方法即可, getMaxTries返回最大重试次数,超过这个次数还没有更新成功就抛出TimeoutException; getNewValue方法返回依据当前cas和缓存值,你希望设置的更新值。看一个cas更详细的例子,开100个线程递增缓冲中的变量a,采用cas才能保证最后a会等于100: import  java.util.concurrent.CountDownLatch; import  net.rubyeye.xmemcached.CASOperation; import  net.rubyeye.xmemcached.XMemcachedClient; /**  * 测试CAS  *  @author  dennis   */ class  CASThread  extends  Thread {      private  XMemcachedClient mc;      private  CountDownLatch cd;      public  CASThread(XMemcachedClient mc, CountDownLatch cdl) {          super ();          this .mc  =  mc;          this .cd  =  cdl;     }      public   void  run() {          try  {              if  (mc.cas( " a " 0 new  CASOperation() {                 @Override                  public   int  getMaxTries() {                      return   50 ;                 }                 @Override                  public  Object getNewValue( long  currentCAS, Object currentValue) {                     System.out.println( " currentValue= "   +  currentValue                              +   " ,currentCAS= "   +  currentCAS);                      return  ((Integer) currentValue).intValue()  +   1 ;                 }             }))                  this .cd.countDown();         }  catch  (Exception e) {             e.printStackTrace();         }     } } public   class  CASTest {      static   int  NUM  =   100 ;      public   static   void  main(String[] args)  throws  Exception {         XMemcachedClient mc  =   new  XMemcachedClient();         mc.addServer( " 192.168.222.100 " 11211 );          //  设置初始值为0         mc.set( " a " 0 0 );         CountDownLatch cdl  =   new  CountDownLatch(NUM);          //  开NUM个线程递增变量a          for  ( int  i  =   0 ; i  <  NUM; i ++ )              new  CASThread(mc, cdl).start();         cdl.await();          //  打印结果,最后结果应该为NUM         System.out.println( " result= "   +  mc.get( " a " ));         mc.shutdown();     } }     最高重试次数设置成了50,观察输出你就会知道cas冲突在高并发下非常频繁,这个操作应当慎用。     说完cas,我们再来看下xmemcached对分布的支持。 1、如何添加多个memcached server? 通过XMemcachdClient.addServer(String ip,int port)方法,             XMemcachedClient mc  =   new  XMemcachedClient();             mc.addServer(ip1, port1);             mc.addServer(ip2, port2);             mc.addServer(ip3, port3);             mc.addServer(ip4, port3); 2、怎么分布? 在添加了>=2个memcached server后,对 XMemcachdClient的存储、删除等操作都将默认根据key的哈希值模连接数的余数做分布,这也是spymemcached默认的分布算法。这个算法简单快速,然而在添加或者移除memcached server后,缓存会大面积失效需要重组,这个代价太高,因此还有所谓Consistent Hashing算法,通过将memcached节点分布在一个0-2^128-1的环上,发送数据到某个节点经过的跳跃次数可以缩减到O(lgn)次,并且在添加或者移除节点时最大限度的降低影响,这个算法的思想其实来源于p2p网络的路由算法,不过路由算法比这个复杂多了,毕竟memcached的 分布是在客户端,因此不需要节点之间的通讯和路由表的存储更新等。这个算法在java上的实现可以通过TreeMap红黑树,具体可以参考 这里和 这里。   在xmemcached启动Consistent Hashing如下: XMemcachedClient client  =   new  XMemcachedClient( new  KetamaMemcachedSessionLocator(HashAlgorithm.CRC32_HASH)); client.addServer(ip,  12000 ); client.addServer(ip,  12001 ); client.addServer(ip,  11211 ); client.addServer(ip,  12003 ); client.addServer(ip,  12004 );   散列函数采用CRC32,你也可以采用其他散列函数,具体看场景测试而定,散列函数决定了你的查找节点效率和缓存重新分布的均衡程度。    文章转自庄周梦蝶  ,原文发布时间 2009-03-09 相关资源:敏捷开发V1.0.pptx
    最新回复(0)