改进基于filter的远程分布式session存储

<!--StartFragment-->

 

参考了网上一些资料,实现了session通过filter存储到memcached服务器上.

(参见: http://ooft.javaeye.com/blog/537841 )

实现方式:

a)    通过MemcachedSessionFilter过滤器拦截cookie,取得的sessionId,通过sessionId构造新的HttpServletRequestWrapper对象,传给后面的应用.

b)    继承重构HttpServletRequestWrapper,HttpSessionWrapper类,覆盖原来和session存取相关的方法呢,都通过SessionService类来实现.

c)    SessionService连接memcached服务,以sessionId作为key,存取的对象是一个map.map的内容即为session的内容.

d)    读取数据时,先通过sessionId从memcached服务器上获取整个map对象,再以session的attributeName作为key从map中获取数据对象.写数据的方式与读数据类似,先获取map,然后修改map中的值,然后将整个map保存到memcached服务器上.

改进内容:

(1)    使用xmemcached客户端代替java memcached client.

XMemcached同样是基于java nio的客户端,java nio相比于传统阻塞io模型来说,有效率高(特别在高并发下)和资源耗费相对较少的优点。

 

(2)    对修改和删除session属性时,使用cas方法实现,防止在并发时出现数据覆盖的问题.

 

原来的代码:

Java代码 复制代码
  1. public void saveSession(String id, Map session) {   
  2.   
  3.  long s1= System.currentTimeMillis();   
  4.   
  5.  MemCachedClient mc = this.getMemCachedClient();   
  6.   
  7.  mc.replace(id, session);   
  8.   
  9.  System.out.print("saveSession");   
  10.   
  11.  System.out.println(System.currentTimeMillis() -s1);   
  12.   
  13. }  
public void saveSession(String id, Map session) {

 long s1= System.currentTimeMillis();

 MemCachedClient mc = this.getMemCachedClient();

 mc.replace(id, session);

 System.out.print("saveSession");

 System.out.println(System.currentTimeMillis() -s1);

}

 

 

 

  其中保存进去的 session 是一个通过 get 方法从 memcached 上获取的 map 对象 , map 中的值修改以后 , map 对象替换服务器上的对象 . 如果在多台机器并发的情况下 , 很可能出现一个线程写进去的数据被其它的覆盖 .

 

改进后的代码:

   Memcached是通过cas协议实现原子更新,所谓原子更新就是compare and set,原理类似乐观锁,每次请求存储某个数据同时要附带一个cas值,memcached比对这个cas值与当前存储数据的cas值是否相等,如果相等就让新的数据覆盖老的数据,如果不相等就认为更新失败,这在并发环境下特别有用。

Java代码 复制代码
  1. public void saveSession(String id,String key, Object arg1) {   
  2.     long s1= System.currentTimeMillis();   
  3.     final String k=key;   
  4.     final Object o=arg1;   
  5.   
  6.     try {              
  7.            mc.cas(id,0,new CASOperation<Map>(){   
  8.         //尝试更新5次   
  9.         public int getMaxTries() {   
  10.             return 5;   
  11.         }                  
  12.         public Map getNewValue(long currentCAS, Map map) {   
  13.             map.put(k, o);   
  14.             return map;   
  15.         }});   
  16.            System.out.print("saveSession");        
  17.     }      
  18.     finally{   
  19.         System.out.println(System.currentTimeMillis() -s1);   
  20.     }   
  21. }  
发布了26 篇原创文章 · 获赞 0 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/sameseam/article/details/5055241
今日推荐