基于redis实现分布式Session
学习到好的知识还是需要记录下来的。
开发环境 asp.net mvc4,iis。asp.net 自带的session机制存在诸多不好的地方。先只要列出几点。
- asp.net mvc 默认的session模式mode为InProc。很多向我这样的菜鸟是没有意识去修改它的。这模式下的话是session的保存的东西是存储在服务器内存的。而服务器的资源是有限的,当用户访问量大的时候,对服务器的内存压力会比极大,很可能会导致内存溢出。
- Session 支持其它模式。mode="SQLServer",mode="StateServer".这两种模式下,会比默认的方式减低了服务压力,但在每次请求时,不管你用不用session,都会为你准备好,这其实是很浪费时间的。
- 如果你没有关闭session,SessionStateModule就一直在工作,会对每个请求执行一系列的调用,浪费资源。
- 当iis或服务器重启,session会丢失。为防止内存溢出,服务器会长时间把没有活跃的session从内存删除。这在用户体验的角度来说,是非常不好的。而且session产出之后,需要服务器一直来维护(比如过期,从内存中删掉),这也是需要消耗服务器资源的。本身windows服务器的成本就不低了。这么耗着,是挺浪费的。
- 不能保证过期时间。session默认设置过期时间为20分钟。但我在实际的应用中经常会出现不到20分钟就不能使用的状况。session里面存的容量太大导致的。
- 不能跨服务器访问。session是存在服务器内存的。不能为其他服务器所访问。对部署分布式系统是非常不利的。
为了解决以上的问题,我现在的解决方案是:redis+cookie。首先说明一下为什么选择这么做的原因。
redis是一个key-value存储系统。
- 操作非常的方便,容易上手。跟它同类型的有memcached。但服务器断电后数据并不会丢失,这是redis好的一个点。
- 其次,redis支持分布式拓展,且方便。关于两者比较,这里不做细说。
cookie的话,主流的浏览器都支持的了。可能有人会说会有人会禁用cookie,这个只能提示用户开启来解决了。大部分的人还是不会关闭的喔。
业务如下:保存用户的登录状态,设置过期时间为7天。
user的数据结构
public class user{
public string userid{get;set;}
public string username{get;set;}
public string gender{get;set;}
public string avatar{get;set;}
public int age{get;set;}
}
该将什么数据保存在cookie中呢。这个时候是需要认真看看cookie的本意了。cookie,小饼干。cookie是浏览器专用,用来记录保存数据的工具。保存在cookie的文件不能过大。好像是每个网站最多3M吧,要省着点花。哈哈。。。。
我选择把userid的数据保存在cookie中,为什么呢。首先userid的来源是数据库主键,是唯一。二,userid也无实际的意义。窃取了并不会获得很多的信息。
初期准备
- userid需要进行可逆加密。原因:虽说userid被选择来暴露的,但还是得保护一下咯。为什么是可逆加密呢。这个数据是需要使用的,当然是需要可逆的。我在哪里使用到呢。这个userid与redis的key有相关。
- 既然说不需要使用内置session了。那就关闭它。要不然就这样让它在那里耗着服务器资源是太好了。怎么关闭呢。全局关闭session的方法:在web.config的<system.web></system.web>中加入 <sessionState mode="Off"></sessionState>。这就成功关闭咯。哈哈哈。。。
- 准备好RedisHelper。这主要是对redis相关操作的封装。还是很容易理解和包装的。要注意程序池的分配。
总算准备好了。
步骤
- 在用户登录的时候,把加密后的userid写入cookie.设置有效期为7天。
- 写入cookie后,把用户数据写入redis。redis的可以值为“u”+userid,value为user实体。同时也要设置key-value的有效期为7天。这就完成了基本的存储。
- 用户拥有cookie之后,每次访问,用户都会把cookie发送到服务器。这个时候需要对cookie进行实时刷新有效期。这里该怎么做是最好的呢。还要想。特性吧。为什么要这步呢?用户cookie的有效期是7天,但是用户在7天内登录的话,是要刷新cookie的有效期的喔。
- 实时刷新redis中"u"+userid键值对的有效期。在刷新cookie时,随后就去刷新redis吧。
- 判断cookie是否过期或有效。先判断cookie的有效期,其次获取redis对应的键值对。如果redis中查找不到对应的键值对,也就是过期的节奏了。
这就写完了。写的有点乱。。。。。有空整理好代码贴上去。
最后贴上一些很不错的与本文相关的文章。感谢他们的分享。爱分享的人与你们同在。
http://blog.csdn.net/fangaoxin/article/details/6952954 Cookie/Session机制详解
http://www.cnblogs.com/fish-li/archive/2011/07/31/2123191.html Session,有没有必要使用它
http://www.2cto.com/kf/201205/133998.html 配置Session变量的生命周期