`
sameseam
  • 浏览: 21523 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

改进基于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. publicvoidsaveSession(Stringid,Mapsession){
  2. longs1=System.currentTimeMillis();
  3. MemCachedClientmc=this.getMemCachedClient();
  4. mc.replace(id,session);
  5. System.out.print("saveSession");
  6. System.out.println(System.currentTimeMillis()-s1);
  7. }

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

改进后的代码:

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

Java代码 复制代码
  1. publicvoidsaveSession(Stringid,Stringkey,Objectarg1){
  2. longs1=System.currentTimeMillis();
  3. finalStringk=key;
  4. finalObjecto=arg1;
  5. try{
  6. mc.cas(id,0,newCASOperation<Map>(){
  7. //尝试更新5次
  8. publicintgetMaxTries(){
  9. return5;
  10. }
  11. publicMapgetNewValue(longcurrentCAS,Mapmap){
  12. map.put(k,o);
  13. returnmap;
  14. }});
  15. System.out.print("saveSession");
  16. }
  17. finally{
  18. System.out.println(System.currentTimeMillis()-s1);
  19. }
  20. }
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics