分布式缓存扩展Session机制_.NET_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > .NET > 分布式缓存扩展Session机制

分布式缓存扩展Session机制

 2013/11/13 2:45:24  贰毛  博客园  我要评论(0)
  • 摘要:为什么要把Session放在缓存中Session是我们常用的状态保持的对象,它通常会生成一个唯一的SessionId以Cookie的方式存在浏览器端,而Session本身会保存在服务器端。虽说我们用Session很方便的实现状态保持,但是Session也带来了很多弊端,下面我们一步一步来分析Session的一些弊端以及用什么方式去改变它:一、当mode="InProc"时:1.因为网站会因为各种原因重启,照成数据丢失,在线用户全部下线。2.Session保存的东西越来越多
  • 标签:缓存

为什么要把Session放在缓存

  Session是我们常用的状态保持的对象,它通常会生成一个唯一的SessionId以Cookie的方式存在浏览器端,而Session本身会保存在服务器端。

  虽说我们用Session很方便的实现状态保持,但是Session也带来了很多弊端,下面我们一步一步来分析Session的一些弊端以及用什么方式去改变它:

  

  一、当mode="InProc"时:

    1.因为网站会因为各种原因重启,照成数据丢失,在线用户全部下线。

    2.Session保存的东西越来越多,占用服务器内存也就越来越大,服务器内存压力也会越来越大。

    3.Session存在服务器内存中,不能在多台服务器之间共享,扩展性收到了影响。

    -----解决方案:model="SQLServer"或者model="StateServer"...

  二、当model="SQLServer"或者model="StateServer"时:

    1.无论我们是否要使用SessionState,SessionStateModule一直在工作,每一个用户请求都会去处理SessionState,执行一些列的调用,其中还可能涉及到序列化和反序列化,这样造成了资源浪费,影响性能。

    2.每个用户对应一个SessionId,当一个用户同时打开两个页面的时候、或者一个页面中夹杂着IFrame、或者带着异步请求,这样算属于单个用户并发吧?!HttpHandler处理的时候是会对Session进行加锁的,当一个页面处理慢的时候会锁住当前的Session,后面的页面是不是也在等待当前Session的释放,就这样就照成一个问题——Session影响并发(单个用户并发)。虽说这种情况很少会出现,但是我们在处理一些特殊请求的时候,确实需要注意一下这个细节。对于上面所说的相信大家都有所理解,Session影响并发,可能没有太过关注过,下面举个例子试一试是不是这样的情况!

 

    先创建一个主窗体,三个父窗体,我注册了HttpModule来看一下执行的流程,Test_2页面线程睡眠5秒...

    

 

    在未使用Session的情况下...

    

    

     然后我在主窗体后台类中使用了Session    Session["test"]="test"; 会发现Test_3被阻塞了...

    

    

     解决方案:使用分布式缓存,最近有很多比较火热的分布式缓存系统,如:Memcached、Redis...

    因为Redis可以实现数据持久化,支持多重数据类型,可能应用场景更广泛一些,所以之前用了Redis,这次就那Redis来做例子,不过其他的实现方式也一样一样了...

    

  ------------------------------------------------------------------------------------------------------------------------------------------------------

 

    首先分析一下我们怎么来设计这个Session,我的想法是每个SessionId对应一个Dictionary<string,Object>,SessionId用Guid表示,也是以Cookie的形式发送在客户端,Session为键,Dictionary为值存放在Redis里...

    Session——SessionId{Dictionary<string,Object>}

          SessionId{Dictionary<string,Object>}

          SessionId{Dictionary<string,Object>}

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;

//使用Redis的命名空间
namespace ServiceStack.Redis {
  //把Session作为Redis的扩展方法: 三要素——静态类、静态方法、this关键字
public static class RedisHelper { //private static RedisClient Redis = new RedisClient("127.0.0.1", 6379);     
//设置Session public static bool SetSession(this RedisClient Redis, string key, object value) { var requestCookie = HttpContext.Current.Request.Cookies["SessionId"]; string sessionId; if (requestCookie == null) { sessionId = Guid.NewGuid().ToString(); } else { sessionId = requestCookie.Value; } Redis.Expire(sessionId, 20 * 60); HttpContext.Current.Response.SetCookie(new HttpCookie("SessionId", sessionId)); if (Redis.Exists(sessionId) == 1 ? true : false) { var newDir = Redis.Get<Dictionary<string, object>>(sessionId) as Dictionary<string, object>; if (newDir == null) { return false; } if (newDir.ContainsKey(key)) { newDir.Remove(key); } newDir[key] = value; Redis.Set<Dictionary<string, object>>(sessionId, newDir); return true; } else { Dictionary<string, object> dic = new Dictionary<string, object>(); dic.Add(key, value); Redis.Set<Dictionary<string, object>>(sessionId, dic); return true; } }

     //删除Session
public static bool DeleteSession(this RedisClient Redis, string key) { var requestCookie = HttpContext.Current.Request.Cookies["SessionId"]; string sessionId; if (requestCookie == null) { return false; } sessionId = requestCookie.Value; Redis.Expire(sessionId, 20 * 60); Dictionary<string, object> dic = Redis.Get<Dictionary<string, object>>(sessionId); if (dic == null) { return false; } if (dic.ContainsKey(key)) { dic.Remove(key); Redis.Set<Dictionary<string, object>>(sessionId, dic); } return true; }

      //获取Session
public static object GetSession(this RedisClient Redis, string key) { var requestCookie = HttpContext.Current.Request.Cookies["SessionId"]; string sessionId; if (requestCookie == null) { return null; } sessionId = requestCookie.Value; Dictionary<string, object> dic = Redis.Get<Dictionary<string, object>>(sessionId); if (dic == null) { return null; } if (dic.ContainsKey(key)) { Redis.Expire(sessionId, 20 * 60); return dic[key]; } return null; } } }

    优点:  

        1.解决了session的性能问题;

        2.解决了应用程序的可扩展性;

        3.内存之间的共享;

        4.Session丢失的问题;

          

    这是自己对Redis的一个扩展Session,不知道是否算优,欢迎大牛拍砖纠正;

 

发表评论
用户名: 匿名